2016前端開發技術巡禮
作者:殷勇
編輯:尾尾2016年馬上過去了,像過去六年中的每一年一樣,Web前端領域又產生了「面目全非」而又「耳目一新」的變化,不但舊事物持續不斷地被淘汰,新事物也難保坐久江山,大有岌岌可危之勢。開源界如群雄逐鹿,不斷生產新的概念、新的框架、新的工具,去年中一些流行的技術今年大多得到了進一步的演進和升級,活躍度非常高,卻仍然不能保證前端的未來屬於它們。在今年整體資本市場冷卻的大環境下,to B業務的創業公司顯現出了較強的生命力,這種類型的業務也給Web前端的工作帶來了明顯的差異性,工程師整體技能方向也展露出一絲不一樣的分支。本文將從下至上、由低到高的維度盤點過去一年中Web前端領域發生的重要事件以及影響未來2017的關鍵性因素。視野所限,不盡完整。目錄
一、更新的網路與軟體環境
1.1 HTTP/2 的持續普及
1.2 Internet Explorer 8
二、如何編寫(Java)Script
2.1 ES2016?ES2017?Babel!
2.2 TypeScript
2.3 promise、generator 與 async/await
2.4 fetch
三、Node.js服務與工具
- Koa 2
四、框架紛爭
4.1 jQuery已死?
4.2 Angular 2
4.3 Vue.js 2.0
4.4 React
4.5 React-Native
4.6 Redux 與 Mobx
4.7 Bootstrap 4
五、工程化與架構
5.1 Rollup 與 Webpack 2
5.2 npm、jspm、Bower與Yarn
5.3 同構
六、未來技術與職業培養
6.1 大數據方向
6.2 WebVR
6.3 WebAssembly
6.4 WebComponents
6.5 關於微信小程序
七、總結
7.1 工程化
7.2 角色定位
7.3 寫在最後
一、更新的網路與軟體環境
1.1 HTTP/2 的持續普及
今年中,幾乎所有的現代桌面瀏覽器都已經支持了HTTP/2協議,移動端依靠降級為SPDY依舊可以覆蓋幾乎所有平台,這樣使得從協議上優化頁面的性能成為了可能。
同時,前端靜態資源打包的必要性成為了一定程度上的爭論焦點,打包合併作為傳統的前端性能優化方案,它的存留對前端工程化影響極大,Facebook公司著名的靜態資源動態打包方案的優越性也會被弱化。社區上多篇文章紛紛發表對HTTP/2的性能實驗數據,卻不盡相同。
在2017年,我相信所有大型站點都會切換HTTP/2,但依舊不會放棄對靜態資源打包合併的依賴。而且,對於Server Push等高級特性,也不會有太多的應用。
1.2 Internet Explorer 8
三年前還在考慮兼容IE6的前端技術社區,在前不久天貓宣布不再支持IE8後又引起了一股躁動。IE8是Windows XP操作系統支持的最高IE版本,放棄IE8意味著放棄了使用IE的所有XP用戶。
其實在2016年的今天,前端社區中框架、工具的發展早已不允許IE8的存在,Angular 早在1.3版本就果斷放棄了IE8,React 也在年初的v15版本上宣布放棄。在PC領域,你依舊可以使用像Backbone.js一樣的其他框架繼續對IE進行支持,但無論是從研發效率上還是從運行時效率上,放棄它都是更好的選擇。
由於對HTML5兼容性不佳,在2017年,相信IE9也會逐漸被社區放棄,以取得更好的性能、更少的代碼體積。
二、如何編寫(Java)Script
2.1 ES2016?ES2017?Babel!
去年定稿的ES2015(亦稱ES6)帶來了大量令人激動的新語言特性,並快速被V8和SpiderMonkey所實現。但由於瀏覽器版本碎片化問題,目前編寫生產環境代碼仍然以ES5為主。今年年中發布的ES2017帶來的新特性數量少的可憐,但這正好給了瀏覽器廠商消化ES2015的時間,在ES2017到來之前喘口氣——是的,明年的ES2017勢必又會帶來一大波新特性。
JS解釋引擎對新特性的支持程度並不能阻礙狂熱的開發者使用他們,在接下來的很長時間,業界對Babel的依賴必然有增無減。Babel生態對下一代ECMAScript的影響會進一步加大,人們通過先增加新的Babel-plugin,後向ECMA提案的方式成為了ECMAScript進化的常態。開發者編寫的代碼能直接運行在瀏覽器上的會越來越少。
但使用Babel導致的編譯後代碼體積增大的問題並沒有被特別關注,由於polyfill可能被重複引入,部署到生產環境的代碼帶有相當一部分冗餘。
2.2 TypeScript
作為ECMAScript語言的超集,TypeScript在今年取得了優異的成績,Angular 2放棄了傳說中的AtScript,成為了TypeScript的最大客戶。人們可以像編寫Java一樣編寫JavaScript,有效提升了代碼的表述性和類型安全性。
但凡事有兩面,TypeScript的特性也在不斷升級,在生產環境中,你可能需要一套規範來約束開發者,防止濫用導致的不兼容,這反而增加了學習成本、應用複雜性和升級安全性。個中優劣,仍需有大量的工程實踐去積累經驗。
此外,TypeScript也可以看做一種轉譯器,與Babel有著類似的新特性支持。在2017年,我們期待TypeScript與Babel會發展成怎樣的一種微妙關係。
2.3 promise、generator 與 async/await
在回調地獄問題上,近兩年我們不斷被新的方案亂花了眼。過去我們會利用async來簡化非同步流的設計,直到「正房」Promise的到來。但它們只是callback模式的語法糖,並沒有完全消除callback的使用。
ES2015帶來的generator/yield似乎成為了解決非同步編程的一大法寶,雖然它並非為解決非同步編程所設計的。但generaor的運行是十分繁瑣的,因此另一個工具co又成為了使用generator的必備之選。Node.js社區的Koa框架初始就設計為使用generator編寫洋蔥皮一樣的控制流。
但曇花一現,轉眼間async/await的語法,配合Promise編寫非同步代碼的方式立即席捲整個前端社區,雖然async/await仍然在ES2017的草案中,但在今天,不寫async/await立刻顯得你的設計落後社區平均水平一大截。
在Node.js上,v7已經支持在harmony參數下的async/await直接解釋,在明年4月份的v8中,將會正式支持,屆時,Koa 2的正式版也會發布,幾乎完全摒棄了generator。
2.4 fetch
受到回調問題的影響,傳統的XMLHttpRequest有被fetch API 取代之勢。如今,成熟的polyfill如whatwg-fetch、node-fetch、isomorphic-fetch在npm上的每日下載量都非常大,即便對於兼容性不好的移動端,開發者也不願使用繁瑣的AJAX。藉助async/await的語法,使用fetch API能讓代碼更簡潔。
三、Node.js服務與工具
3.1 Koa 2
Koa與流行的Express屬於「同根生」的關係,它們由同一團隊打造。相比Express,新的Koa框架更輕量、更靈活。但Koa的設計在短時間內曾經出現了較大的變動,這主要受到了async/await語法對非同步編程的影響。在v2版本中,Koa的middleware拋棄generator轉而支持async,所有第三方middleware實現,要麼自行升級,要麼使用Koa-convert進行包裝轉換。
目前Koa在Node.js社區的HTTP服務端框架中受到關注度比較高,不過其在npm上latest目前仍處於1.x階段,預計在2017年4月份發布Node.js v8後,就會升級到2.x。
Koa的輕量級設計意味著你需要大量第三方中間件去實現一個完整的Web應用,目前鮮有看到對Koa的大規模重度使用,因此也就對其無從評價。相信在明年,越來越多的產品應該會嘗試部署Koa 2,屆時,對第三方資源的依賴衝突也會尖銳起來,這需要一個過程才能讓Koa的生態完備起來。預計在2018年,我們會得到一個足夠健壯的Koa技術棧。這會促進Node.js在服務端領域的擴展,輕量級的Web服務將會逐漸成為市場上的主流。
四、框架紛爭
4.1 jQuery已死?
今年六月份jQuery發布了3.0版本,距離2.0發布已經有三年多的時間,但重大的更新幾乎沒有。由於老舊瀏覽器的逐漸放棄和升級,jQuery需要處理的瀏覽器兼容性問題越來越少,專註於API易用性和效率越來越多。
隨著如Angular、React、Ember、Vue.js等大量具備視圖數據單雙向綁定能力的框架被普及,使用jQuery編寫指令式的代碼操作DOM的人越來越少。早在2015年便有人聲稱jQuery已死,社區中也進行了大量雷同的討論,今天我們看到確實jQuery的地位已大不如前,著名的sizzle選擇器在今天已完全可由querySelector*原生方法替代,操作DOM也可以由框架根據數據的變動自動完成。
明年jQuery在構建大型前端產品的過程中的依賴會被持續弱化,但其對瀏覽器特性的理解和積澱將對現有的和未來的類Angular的MVVM框架的開發依舊具有很大的借鑒意義。
4.2 Angular 2
好事多磨,Angular 2的正式版終於在今年下半年發布,相比於1.x,新的版本幾乎是完全重新開發的框架,已經很難從設計中找到1.x的影子。陡峭的學習曲線也隨之而來,npm、ES2015 Modules、Decorator、TypeScript、Zone.js、RxJS、JIT/AOT、E2E Test,幾乎都是業界這兩年中的最新概念,這著實給初學者帶來了不小的困難。
Angular 2也更面向於開發單頁應用(SPA),這是對ES2015 Modules語法描述的模塊進行打包(bundle)的必然結果,因此Angular 2也更依賴於Webpack等「bundler」工具。
雖然Angular 聲稱支持TypeScript、ECMAScript和Dart三種語言,不過顯然業界對Dart沒什麼太大興趣,而對於ECMAScript和TypeScript,兩種語言模式下Angular 2在API和構建流程上都有著隱式的(文檔標註不明的)差異化,這必然會給開發者以困擾。加上業界第三方工具和組件的支持有限,TypeScript幾乎是現在開發者唯一的選擇。
此外,Angular團隊已聲明並沒有完全放棄對1.x組件的支持,通過特有的兼容API,你可以在2.x中使用針對1.x開發的組件。鑒於不明確的風險,相信很少有團隊願意這樣折騰。
現在在產品中使用Angular 2,在架構上,你需要考慮生產環境和開發環境下兩種完全不同的構建模式,也就是JIT和AOT,這需要你有兩套不一樣的編譯流程和配置文件。在不同環境下模塊是否符合期望,可以用E2E、spec等方式來進行自動化測試,好的,那麼Angular 2的測試API又可能成了技術壁壘,它的複雜度可能更甚Angular本身。可以確信,在業務壓力的迫使下,絕大部分團隊都會放棄編寫測試。
總之,Angular 2是一個非常具有競爭力的框架,其設計非常具有前瞻性,但也由於太過複雜,很多特性都會成為雞肋,被開發者所無視。由於React和Vue.js的競爭,Angular 2對社區的影響肯定不如其前輩1.x版本,且其更高級的特性如Server Render還沒有被工程化實踐,因此相信業界還會持續觀望,甚至要等到下一個4.x版本的發布。
4.3 Vue.js 2.0
Vue.js 絕對是類MVVM框架中的一匹黑馬,由作者一人打造,更可貴的是作者還是華人。Vue.js在社區內的影響非常之大,特別是2.0的發布,社區快速生產出了無數基於Vue.js的解決方案,這主要還是受益於其簡單的介面API和友好的文檔。可見作為提供商,產品的簡單易用性顯得尤為重要。在性能上,Vue.js基於ES5 Setter,得到了比Angular 1.x臟檢查機製成倍的性能提升。而2.0在模塊化上又更進一步,開發難度更低,維護性更好。可以說Vue.js準確地戳中了普通Web開發者的痛點。在國內,Vue.js與Weex達成了合作,期待能給社區帶來怎樣的驚喜。
4.4 React
目前看來,React似乎仍是今年最流行的數據視圖層解決方案,並且幾乎已經成為了每名前端工程師的標配技能。今年React除了版本從0.14直接躍升至15,放棄了IE8以外,並沒有更多爆髮式的發展。人們對於使用JSX語法編寫Web應用已經習以為常,就像過去十年間寫jQuery一樣。
React的代碼在維護性能上顯而易見,如果JSX編寫得當,在重渲染性能上也具備優勢,但如果只部署在瀏覽器環境中,那麼首屏性能將會受到負面影響,畢竟在現階段,純前端渲染仍然快不過後端渲染,況且後端具備天生的chunked分段輸出優勢。我們在業界中可以看到一些負面的案例,比如某新聞應用利用React全部改寫的case,就是對React的一種誤用,完全不顧其場景劣勢。
圍繞著React發展的替代品和配套工具依舊很活躍,preact以完全兼容的API和小巧的體積為賣點,inferno以更快的速度為賣點,等等。每個框架都想在Virtual DOM上有所創新,但它們的提升都不是革命性的,由此而帶來的第三方插件不兼容性,這種風險是開發者不願承擔的,筆者認為它們最大的意義在於能為React的內部實現提供另外的思路。就像在自然界,生物多樣性是十分必要的,雜交能帶來珍貴的進化優勢。
4.5 React-native
今年是React-native(一下簡稱RN)支持雙端開發的第一年,不斷有團隊分享了自己在RN上的實踐成果,似乎前途一片大好,RN確實有效解決了傳統客戶端受限於發版周期、H5受限於性能的難題,做到了魚和熊掌兼得的理想目標。
但我們仍然需要質疑:首先,RN目前以兩周為周期發布新版本,沒有LTS,每個版本向前不兼容。也就是說,你使用0.39.0的版本編寫bundle代碼,想運行在0.35.0的runtime上,這幾乎會100%出問題。在這種情況下,如何制定客戶端上RN的升級策略?如果升級,那麼業務上如何針對一個以上的runtime版本編寫代碼?如果不升級,那麼這意味著你需要自己維護一個LTS。要知道目前每個RN的版本都會有針對前版本的bug fix,相信沒有團隊有精力可以在一個老版本上同步這些,如果不能,那業務端面對的將是一個始終存在bug的runtime,其開發心理壓力可想而知。
其次,雖然RN聲稱支持Android與iOS雙端,但在實踐中卻存在了極多系統差異性,有些體現在了RN文檔中,有一些則體現在了issue中,包括其他一些問題,GitHub上RN的近700個issue足以讓人望而卻步。如果不能高效處理開發中遇到的各種匪夷所思的問題,那麼工期就會出現嚴重風險。此外,RN在Android和iOS上的性能也不盡相同,Android上更差一些,即便你完成了整個業務功能,卻還要在性能優化上消耗精力。並且無論如何優化,單線程模型既要實現流暢的轉場動畫,又要操作一系列數據,需要很高的技巧才能保證可觀的性能表現。在具體的實踐中,對於H5,往往由於時間關係,業務上先會上一個還算過得去的版本,過後再啟動性能優化。然而對於RN,很有可能達到「過得去」的標準都需要大量的重構工作。
再次,RN雖然以Native渲染元素,但畢竟是運行在JavaScript Core內核之上,依舊是單線程,相對於H5這並沒有對性能有革命性質的提升。Animated動畫、大ListView滾動都是老生常談的性能瓶頸,為了解決一些複雜組件所引起的性能和兼容性問題,諸多團隊紛紛發揮主動能動性,自己建設基於Native的高性能組件,這有兩方面問題,一是不利於分發共享,因為它嚴重依賴特定的客戶端環境,二是它仍依賴客戶端發版,仍需要客戶端的開發,違背了RN最最重要的初衷。可以想像,在大量頻繁引用Native組件後,RN又退化成了H5+Hybrid模式,其UI的高性能優勢將會在設備性能不斷升級下被削弱,同時其無stable版本反而給開發帶來了更多不可預測的風險變數。
最後,RN仍然難以調試和測試,特別是依賴了特定端上組件之後,本地的自動化測試幾乎成為了不可能,而絕大多數客戶端根本不支持自動化測試。而調試只能利用remote debugger有限的能力,在性能分析上都十分不便。
可以說RN的出現帶給了移動開發以獨特的新視角,使得利用JavaScript開發Native成為了可能,NativeScript、Weex等類似的解決方案也發展開來。顯然RN目前最大的問題仍然是不夠成熟和穩定,利用RN替代Native依然存在著諸多風險,這對於重量級的、長期維護的客戶端產品可能並不是特別適合,比如Facebook自己。RN的優勢顯而易見,但其問題也是嚴重的,需要決策者對個方面利弊都有所了解,畢竟這種試錯的成本不算小。
由於時間關係,市場上並沒有一個產品在RN的應用上有著足夠久的實踐經驗,大部分依然屬於「我們把RN部署到客戶端了」的階段,我們也無法預測這門技術的長久表現,現在評價RN的最終價值還為時尚早。在2017年,期待RN團隊能做出更長足的進步,但不要太樂觀,以目前的狀態來看,想達到stable狀態還是有著相當大的難度。
4.6 Redux 與 Mobx
Redux 成功成為了 React 技術棧中的最重要成員之一。與Vue.js一樣,Redux也是憑藉著比其他Flux框架更簡單易懂的API才能脫穎而出。不過已經很快有人開始厭煩它每寫一個應用都要定義action、reducer、store以及一大堆函數式調用的繁瑣做法了。
Mobx也是基於ES5 setter,讓開發者可以不用主動調用action函數就可以觸發視圖刷新,它只需要一個store對象以及幾個decorator就能完成配置,確實比Redux簡單得多。
在數據到視圖同步上,無論使用什麼樣的框架,都有一個至關重要的問題是需要開發者自己操心,那就是在眾多數據變動的情形下,如何保證視圖以最少的但合理的頻率去刷新,以節省極其敏感的性能消耗。在Redux或Mobx上都會出現這個問題,而Mobx尤甚。為了配合提升視圖的性能,你依然需要引入action、transaction等高級概念。在控制流與視圖分離的架構中,這是開發者無可避免的關注點,而對於Angular、Vue.js,框架會幫你做很多事情,開發者需要考慮的自然少了許多。
4.7 Bootstrap 4
Bootstrap 4處於alpha階段已經非常久了,即使現在3.x已經停止了維護,它似乎受到了Twitter公司業務不景氣的影響,GitHub上的issue還非常多。Bootstrap是建設內部平台最佳的CSS框架,特別是對於那些對前端不甚了解的後端工程師。我們不清楚Bootstrap還能堅持多久,如果Twitter不得不放棄它,最好的歸宿可能是把它交給第三方開源社區去維護。
五、工程化與架構
5.1 Rollup 與 Webpack 2
Rollup是近一年興起的又一打包工具,其最大賣點是可以對ES2015 Modules的模塊直接打包,以及引入了Tree-Shaking演算法。通過引入Babel-loader,Webpack一樣可以對ES2015 Modules進行打包,於是Rollup的亮點僅在於Tree-Shaking,這是一種能夠去除冗餘,減少代碼體積的技術。通過分析AST(抽象語法樹),Rollup可以發現那些不會被使用的代碼,並去除它。
不過Tree-Shaking即將不是Rollup的專利了,Webpack 2也將支持,並也原生支持ES6 Modules。這可以說是「旁門左道」對主流派系進行貢獻的一個典型案例。
Webpack是去年大熱的打包工具,儼然已經成為了替代grunt/gulp的最新構建工具,但顯然並不是這樣。筆者一直認為Webpack作為一個module bundler,做了太多與其無關的事情,從而表象上看來這就是一個工程構建工具。經典的構建需要有任務的概念,然後控制任務的執行順序,這正是Ant、Grunt、Gulp做的事情。Webpack不是這樣,它最重要的概念是entry,一個或者多個,它必須是類JavaScript語言編寫的磁碟文件,所有其他如CSS、HTML都是圍繞著entry被處理的。估計你很難一眼從配置文件中看出Webpack對當前項目進行了怎樣的「構建」,不過似乎社區中並沒有人提出過異議,一切都運行得很好。
題外話:如何使用Webpack構建一個沒有任何JavaScript代碼的工程?
新的Angular 2使用Webpack 2編譯效果更加,不過,已經提了一年的Webpack 2,至今仍處於beta階段,好在現在已經rc,相信離release不遠了。
5.2 npm、jspm、Bower與Yarn
在模塊管理器這裡,npm依舊是王者,但要說明的是,npm的全稱是node package mamager,主要用來管理運行在Node上的模塊,但現在卻託管了大量只能運行在瀏覽器上的模塊。造成這種現象的幾個原因:
- Webpack的大量使用,使得前端也可以並習慣於使用CommonJS類型的模塊;
- 沒有更合適的替代者,Bower以前不是,以後更不會是。
前端的模塊化規範過去一直處於戰國紛爭的年代。在Node上CommonJS沒什麼意見。在瀏覽器上,雖然現在有了ES2015 Modules,卻缺少了模塊載入器,未來可能是SystemJS,但現在仍處於草案階段。無論哪種,都仍處於JavaScript語言層面,而完整的前端模塊化還要包括CSS與HTML,以及一些二進位資源。目前最貼近的方案也就只能是JSX+CSS in JS的模式了,這在Webpack環境下大行其道。這種現象甚至影響了Angular 2、Ember 2等框架的設計。從這點看來,jspm只是一個加了層包裝的殼子,完全沒有任何優勢。
npm本身也存在著各種問題,這在實踐中總會影響效率、安全以及一致性,Facebook果斷地出品了Yarn——npm的替代升級版,支持離線模式、嚴格的依賴版本管理等在工程中非常實用的特性。
至於前端模塊化,JavaScript有CommonJS和ES2015 Modules就夠了,但工程中的組件,可能還需要在不同的框架環境中重複被開發,它們依舊不兼容。未來的話,WebComponents可能是一個比較優越的方案。
5.3 同構
同構的設計在軟體行業早就被提出,不過在Web前端,還是在Node.js、特別是React的出現後,才真正成為了可能,因為React內核的運行並不依賴於瀏覽器DOM環境。
React的同構是一個比較低成本的方案,只要注意代碼的執行環境,前後端確實可以共享很大一部分代碼,隨之帶來的一大收益是有效克服了SPA這種前端渲染的頁面在首屏性能上的瓶頸,這是所有具備視圖能力的框架Angular、Vue.js、React等的共性問題,而現在,它們都在一種程度上支持server render。
可以想到的做前後端同構面臨的幾個問題:
- 靜態資源如何引入,CSS in JS模式需要考慮在Node.js上的兼容性;
- 數據介面如何fetch,在瀏覽器上是AJAX,在Node.js上是什麼;
- 如何做路由同構,瀏覽器無刷新切換頁面,新路由在服務端可用;
- 大量DOM渲染如何避免阻塞Node.js的執行進程
目前GitHub上star較多的同構框架包括Vue.js的nuxt和React的next.js,以及數據存儲全包的meteor。可以肯定的是,不論它們是否能部署在生產環境中,都不可能滿足你的所有需求,適當的重新架構是必要的,在這個新的領域,沒有太多的經驗可以借鑒。
六、未來技術與職業培養
6.1 大數據方向
越來越多做toB業務的公司對前端的需求都是在數據可視化上,或者更通俗一些——報表。這個部分在從前通常都是前端工程師嗤之以鼻的方向,認為無聊、沒技術。不過在移動端時代,特別是大數據時代,對此類技能的需求增多,技術的含金量也持續提升。根據「面向工資編程」的原則,一定會有大量工程師加入進來。
對這個方向的技術技能要求是Canvas、WebGL,但其實絕大多數需求都不需要你直接與底層API打交道,已經有大量第三方工具幫你做到了,不乏非常優秀的框架。如百度的ECharts,國外的Chart.js、Highcharts、D3.js等等,特別是D3.js,幾乎是大數據前端方向的神器,非常值得學習。
話說回來,作為工程師,心存憂患意識,一定不能以學會這幾款工具就滿足,在實際的業務場景中,更多的需要你擴展框架,生產自己的組件,這需要你具備一定的數學、圖形和OpenGL底層知識,可以說是非常大的技術壁壘和入門門檻。
6.2 WebVR
今年可以說是VR技術爆髮式的一年,市場上推出了多款VR遊戲設備,而淘寶更是開發出了平民的buy+購物體驗,等普及開來,幾乎可以顛覆傳統的網上購物方式。
VR的開發離不開對3D環境的構建,WebVR標準還在草案階段,A-Frame可以用來體驗,另一個three.js框架是一個比較成熟的構建3D場景的工具,除了能在未來的VR應用中大顯身手,同樣也在構建極大豐富的3D交互移動端頁面中顯得必不可少,淘寶就是國內這方面的先驅。
6.3 WebAssembly
asm.js已發展成WebAssembly,由谷歌、微軟、蘋果和Mozilla四家共同推動,似乎是非常喜人樂見的事情,畢竟主要瀏覽器內核廠商都在這裡了。不過合作的一大問題就是低效,今年終於有了可以演示的demo,允許編寫C++代碼來運行在瀏覽器上了,你需要下載一大堆依賴庫,以及一次非常耗時的編譯,不過好歹是個進步。
短時間內,我們都不太可能改變使用JavaScript編寫前端代碼的現狀,Dart失敗了,只能期望於未來的WebAssembly。有了它,前端在運行時效率、安全性都會上一個台階,其他隨之而來的問題,就只能等到那一天再說了。
6.4 WebComponents
WebComponents能帶給我們什麼呢?HTML Template、Shadow DOM、Custom Element和HTML Import?是的,非常完美的組件化系統。Angular、React的組件化系統中,都是以Custom Element的方式組合HTML,但這都是假象,它們最終都會被編譯成JavaScript才會執行。但WebComponents不一樣,Custom Element原生就可以被瀏覽器解析,DOM元素本身的方法都可以自定義,而且元素內部的子元素、樣式,由於Shadow DOM的存在,不會污染全局空間,真正成為了一個沙箱,組件化就應該是這個樣子,外部只關心介面,不關心也不能操縱內部的實現。
當前的組件化,無不依賴於某一特定的框架環境,或者是Angular,或者是React,想移植就需要翻盤推倒重來,也就是說他們是不兼容的。有了WebComponents,作為瀏覽器廠商共同遵循和支持的標準,這一現狀將極有可能被改寫。
未來的前端組件化分發將不會是npm那麼簡單,可能只是引用一個HTML文件,更有可能的是包含CSS、HTML、JavaScript和其他二進位資源的一個目錄。
目前只有最新的Chrome完全支持WebComponents的所有特性,所以距離真正應用它還尚需時日。由於技術上的限制,WebComponents polyfill的能力都非常受限,Shadow DOM不可能實現,而其他三者則更多需要離線編譯實現,可以參考Vue.js 2的實現,非常類似於WebComponents。
6.5 關於微信小程序
微信小程序對於今年不得不說,卻也無話可說。依託於龐大的用戶量,微信官方出品了自有的一套開發技術棧,只能說給繁雜的前端開發又填了一個角色——微信前端工程師。
七、總結
最後還有幾點需要說明。
7.1 工程化
首先,現在業界都在大談前端工程化,人人學構建,個個會打包。鄙人認為,工程化的要點在於「平衡諸方案利弊,取各指標的加權收益最大化」。僅僅加入了項目構建是遠遠不夠的,在實踐中,我們經常需要考慮的方向大可以分為兩種:一是研發效率,這直接應該響應業務需求的能力;二是運行時性能,這直接影響用戶的使用體驗,同時也是產品經理所關心的。這兩點都直接影響了公司的收入和業績。
具體到細節的問題上來,比如說:
- 靜態資源如果組織和打包,對於具備眾多頁面的產品,考慮到不斷的迭代更新,如何打包能讓用戶的代碼下載量最少(性能)?不要說使用Webpack打成一個包,也不要說編譯common chunk就萬事大吉了,難道還需要不斷地調整編譯腳本(效率)?改錯了怎麼辦?有測試方案么?
- 利用Angular特別是React構建純前端渲染頁面,首屏性能如何保證(性能)?引入服務端同構渲染,好的,那麼服務端由誰來編寫?想來必是由前端工程師來編寫,那麼服務端的數據層架構是怎麼樣的?運維角度看,前端如何保證服務的穩定(效率)?
- 組件化方案如何制定(效率)?如果保證組件的分發和引用的便捷性?如何保證組件在用戶端的即插即用(性能)?
對於工程師來說,首先需要量化每個指標的權重,然後對於備選方案,逐個計算加權值,取最大值者,這才是科學的技術選型方法論。
然而在業界,很少能看到針對工程化的更深入分享和討論,大多停留在「哪個框架好」,「使用XXX實現XXX」的階段,往往是某一特定方向的優與劣,很少有科學的全局觀。甚至只看到了某一方案的優勢,對其弊端和可持續性避而不談。造成這種現狀的原因是多方面的,一是技術上,工程師能力的原因並沒有考慮得到,二是政治上,工程師需要快速實現某一目標,以取得可見的KPI收益,完成團隊的績效目標,但更多的可能是,國內絕大多數產品的複雜性都還不夠高,根本無需考慮長久的可持續發展和大規模的團隊合作對於技術方案的影響。
因此,你必須接受的現狀是,無論你是否使用CSS預處理器、使用Webpack還是grunt、使用React還是Angular,使用RN還是Hybrid,對於產品極有可能都不是那麼地敏感和重要,往往更取決於決策者的個人喜好。
7.2 角色定位
確實,近兩年,Web前端工程師開始不夠老實,要麼用Node.js插手服務端開發,要麼用RN插手客戶端開發。如何看待這些行為呢?
鄙人以為,涉足服務端開發是沒問題的,因為只涉及到渲染層面,還是屬於「前端」的範疇的。況且,在實際的工程實踐中,已經可以證明,優秀的前端研發體系確實離不開服務端的參與,想想Facebook的BigPipe。不過,這需要服務端良好的分層架構,數據與渲染完全解耦分離,後端工程師只負責業務數據的CRUD,並提供介面,前端工程師從介面中獲取數據,並推送到瀏覽器上。數據解耦是比介面解耦更加優越的方案。因此現在只要你的服務端架構允許,Node.js作為Web服務已經比較成熟,前端負責服務端渲染是完全沒有問題的。
前端涉足客戶端開發也是合理的,畢竟都運行在用戶端,也屬於前端的範疇。拋開阿里系的Weex鄙人不甚了解,NativeScript、RN都還缺乏大規模持續使用的先例,這是與涉足服務端領域的不同,客戶端上的方案都還不夠成熟,工具的限制阻礙了前端向客戶端的轉型,仍然需要時間的考驗。不過時間可能不會很多,未來的Web技術依託高性能硬體以及普及的WebGL、WebRTC、Payment API等能力,在性能和功能上都會挑戰Native的地位。最差的情況,還可以基於Hybrid,利用Native適當擴展能力,這就是合作而非競爭關係了。
總之前端工程師的本仍然在瀏覽器上,就這一點,範圍就足夠廣使得沒人有敢言自己真正「精通」前端。如果條件允許的話,特別是技術成熟之後,涉獵其他領域也是鼓勵的。
7.3 寫在最後
在各種研發角色中,前端註定是一個比較心累的一個。每一年的年末,我們都能看到幾乎完全不一樣的世界,這背後是無數前端人燒腦思考、激情迸發的結果。無論最終產品的流行與否,都推動著前端技術領域的高速更新換代。正是印證了那一句「唯有變化為不變」。作為業務線的研發工程師,我們的職責是甄選最佳組合方案,取得公司利益最大化。這個「最佳」的涉獵面非常廣,取決於設計者的技術視野廣度,也有關於決策者的管理經驗,從來都不是一件簡單的事。
未來的Web前端開發體驗一定是更豐富的,依託WebComponents的標準化組件體系,基於WebAssembly的高性能運行時代碼,以及背靠HTTP/2協議的高速資源載入,前端工程師不必在性能上、兼容性上分散太多精力,從而可以專註於開發具備豐富式交互體驗的下一代Web APP,可能是VR,也可能是遊戲。
在迎接2017的同時,我們仍然要做好心理準備,新的概念、新的框架和工具以及新的語法依舊會源源不斷的生產出來,不完美的現狀也依舊會持續。
由於水平有限,筆者在上述內容中難免有失偏頗,請多包涵。
本文首發於InfoQ微信前端垂直號前端之巔,轉載請在文首註明來源,歡迎前端工程師關注前端之巔。
推薦閱讀: