2016年1月2日 星期六

2015前端生態發展回顧(一)

原文:https://github.com/kuitos/kuitos.github.io/issues/32


引用蘇寧前端架構師的一個總結作為開篇
編程技術及生態發展的三個階段
  • 最初的時候人們忙著補全各種API,代表著他們擁有的東西還很匱乏,需要在語言跟基礎設施上繼續完善
  • 然後就開始各種模式,標誌他們做的東西逐漸變大變複雜,需要更好的組織了
  • 然後就是各類分層MVC,MVP,MVVM之類,可視化開發,自動化測試,團隊協同系統等等,說明重視生產效率了,也就是所謂工程化
處在2015年這個時間段來看,前端生態已經進入了第三階段。看上去好像已經走的挺遠了,實則不然。如果再用人類歷史上的三次工業革命來類比,前端發展其實不過剛剛邁入了蒸汽機時代,開始逐步用工具來替代過往相當一部分的人工作業,但是離電氣時代的自動化流水線作業還有很長一段路要走。回顧一下2015年前端的生態發展,我大致整理了幾個我覺得比較有歷史意義的事件。
按時間順序:
  1. 年初React Native的發布,引領React正式走上歷史舞台。
  2. 3月angular2.0第一個預覽版發布
  3. 5月http/2.0標準正式發布,同月iojs 與nodejs合併。
  4. 6月 ES6 和 WebAssembly 落地
  5. 迄今為止React生態圈影響最大的Flux實現redux發布1.0版本
  6. 8月Facebook公開了在React上應用GraphQL的relay框架的技術預覽版
  7. 9月 React Native for Andriod 發布
  8. 11月伊始,es標準委員會宣布將歷時3年研究的Object.observe從草案中移除,儘管它原本已經是stage2,幾乎已經是ES7的事實標準。雙十一剛一結束,阿里手淘團隊發布了名為無線電商動態化解決方案的Weex,也有人給了它一個更具象的名字,vue native。
  9. 12月,趕在2015的尾巴,aurelia和angular2先後發布beta版。 css方面,postcss & cssnext先後高調走到台前。

觀念的變化

由於近幾年前端的野蠻生長以及前端應用的多元化和複雜化,整個技術形態已經跟幾年前純做頁面的時代完全迥異了。主要觀念的變化總結來看在於一點,現在的前端開發麵向的是web app而不是web page。今天的前端開發模式跟傳統的GUI軟體(如C++、.NET開發的windows客戶端)已經很接近了,而且由於現在前端領域為了解決日益複雜的web業務需求及體量,越來越多的借鑒了傳統客戶端的開發經驗,導致兩者變得越來越趨同。再加上前端一些獨特的特性(免安裝、增量安裝等),工程上的複雜度有過之而無不及。前端如今已經脫離了茹毛飲血、刀耕火種的原始社會,開始步入了工業時代。

框架 & 類庫的變化

今年最火的框架/類庫毫無疑問當屬React了。 React從2014年年中開始廣泛受到開發者關注,但是真正開始在社區獨領風騷還得歸功於2015年初React Native的發布。 React Native的發布使得js統一三端(前端、後端、移動端)開發成為可能(現在這個時間點看可能還是過於理想,但是整體方向還是對的),這一針強心劑吸引了大量開發者的眼球。筆者對此最大的感受就是,我在社區發表一篇react的入門教程級別的軟文便可獲得廣泛關注及轉發,相應的寫angular源碼剖析的準乾貨大部分情況則是門可羅雀😂。
我們挑幾個主流的框架來講講這一層的變化。

React & Redux

React基本簡介可以參考這篇文章React簡介,這裡不再贅述。我們挑幾個核心特徵簡單來講:
  1. virtual dom
    這個可以說是F家工程師超強工程能力的最佳體現了(Relay也算一個),從本質來看它是通過用js object來模擬了一個dom tree,然後將這層virtual dom插在react組件跟真實dom之間,配合強勁的dom diff算法實現它一直標榜的高性能。
  2. jsx
    同樣為了配合react中的組件化開發模式,F家發明了一套新的語法jsx。乍看之下它像是html in js,這也是初接觸的開發者最難以接受的,典型的違背前端推崇多年的表現與業務分離的原則啊。其實這裡要換個角度來看jsx,它並不是html in js,準確來說它是一個用來構建react組件樹的AST。這樣來想你就能理解react中這一看似怪異的設計了。
  3. immutable object
    不可變對像是函數式編程中的重要概念,react的介入使得這一理念在前端社區中流行起來。從目前各種類庫的實現來看,不可變對像在大型應用中擁有傳統可變對像不具備的優勢。尤其在這個內存不值錢的年代。從目前immutable object的良好走勢來看,將來有可能被es納入規範之中。目前可以通過facebook的immutable.js來實現。
Redux則是目前react配套的Flux模式的各種實現(其實現在兩者的關係越來越模糊了)中最火的一個,在此基礎上它引入了函數式編程、單一數據源、不可變數據、中間件等概念。一定程度來講,redux是今年react生態甚至整個前端生態中影響最大的一個框架,它給整個前端技術棧引入了很多新成員,儘管這些概念可能在其他領域已經有了廣泛的應用。雖然它們是否會在大規模的應用實踐中被廣大開發者認可還需要再檢驗,但至少給我們帶來了一些新的思路。其中的單一數據源、不可變數據、中間件等思路目前來看還是非常有價值的,尤其是單一數據源跟不可變數據,很有可能在將來成為大型應用架構中的標配(目前來看至少在應用中構建Store層在當前的前端架構中是勢在必行的)。單一數據源就好比在前端構建了一個集中式數據庫,所有的數據存取操作對像都是它,不單如此它裡面還實現了觸發器,當有insert/update操作時它會對相應組件作rerender動作,這個在各組件之間有數據同步需求的場景下就非常有用了。
至於我對函數式編程的看法,後面單獨闡述。
在我看來,react的優勢並不在組件化,組件化的實現方案多種多樣。 react的優勢在於virtual dom及一個幾乎構成閉環的強大生態,這歸功於Facebook工程師強大的工程能力跟架構能力。 virtual dom將應用表現層從瀏覽器這個基於dom的上下文中抽離出來,通過原生js對像模型的方式使得react具備在任何環境支撐上層表現的能力。上層的渲染引擎可以是canvas、native、服務端甚至是桌面端,只要相應的端提供基於react組件的渲染能力,即可達到一套代碼、或者只要很少的改動就能移植到任一終端環境的效果,這個就非常誇張了。 react從0.14版本之後便將react-dom抽出來變成一個獨立的庫,可見react的野心並不局限於瀏覽器,相反從這點來看,react反而是受到了dom的掣肘。

Angular2 & Vue.js

ng2跟ng1相比是一個完全革命性版本而不是升級版,它是一個為了迎合未來的標準及理念來設計的全新框架,而這些新的理念又無法通過改進ng1.x的方式來實施,所以angular團隊做了這麼一個看似激進的決策,可以理解成重構已經無法滿足需求只能重寫了。 ng2也採用純組件化的開發思路,任何單元對於它來說都是組件。同時,ng2裡面也引入了一些全新的概念(對於前端而言)來提升框架的性能及設計,例如基於worker的數據檢測機制能大幅度提升渲染性能(對應實現是zone.js),基於響應式編程的新的編程模型能更大的改善編碼體驗(對應實現RxJS)。趕在2015年的尾巴,ng2正式發布beta版,對於angular的這次自我革命是否能成功,還有待後續檢驗。另外原angular團隊中出來的一個成員開發了一個類ng2的框架aurelia,有相當的開發者認為它更配稱為ng2,值得關注。
由於阿里在背後的技術實踐及支持,Vue.js今年也開始得到越來越多的關注。 vue相對於angular1.x的優勢在於輕量、易用、更優異的性能及面向組件化的設計,目前發展態勢也非常好,是移動端開發的一個重要技術選型之一。

標準 & 語言的變化

現在回顧起來,2015年是很有意義的一年:這一年是Web誕生25歲週年,也是js誕生的20週年。同時又是ES6標準落地的一年。 ES6是迄今為止ECMAScript標準最大的變革(如果不算上胎死腹中的ES4的話),帶來了一系列令開發者興奮的新特性。從目前es的進化速度來看,es後面應該會變成一個個的feature發布而不是像以前那樣大版本號的方式,所以現在官方也在推薦ES+年份這種叫法而不是ES +版本。

ES2015(ES6) & ES2016(ES7) & TypeScript

6月中ES2015規范正式發布,從ES2015帶來的這些革命性的新語法來看,JS從此具備了用於開發大型應用的語言的基本要素:原生的mudule支持、原生的class關鍵字、更簡潔的api及語法糖,更穩定的數據類型。而這些new features中,有幾個我認為是會影響整個前端發展進程的:
  1. Module & Module Loader
    ES2015中加入的原生模塊機制支持可謂是意義最重大的feature了,且不說目前市面上五花八門的module/loader庫,各種不同實現機制互不兼容也就罷了(其實這也是非常大的問題) ,關鍵是那些模塊定義/裝載語法都醜到爆炸,但是這也是無奈之舉,在沒有語言級別的支持下,js只能做到這一步,正所謂巧婦難為無米之炊。 ES2016中的Module機制借鑒自CommonJS,同時又提供了更優雅的關鍵字及語法(雖然也存在一些問題)。遺憾的是同樣有重大價值的Module Loader在2014年底從ES2015草案中移除了,我猜測可能是對於瀏覽器而言Module Loader的支持遭遇了一些技術上的難點,從而暫時性的捨棄了這一feature。但是一個原生支持的模塊加載器是非常有意義的,相信它不久後還是會回歸到ES規範中(目前由WHATWG組織在單獨維護)。
  2. class
    準確來說class關鍵字只是一個js裡構造函數的語法糖而已,跟直接function寫法無本質區別。只不過有了Class的原生支持後,js的面向對像機制有了更多的可能性,比如衍生的extends關鍵字(雖然也只是語法糖)。
  3. Promise & Reflect API
    Promise的誕生其實已經有幾十年了,它被納入ES規範最大意義在於,它將市面上各種異步實現庫的最佳實踐都標準化了。至於Reflect API,它讓js歷史上第一次具備了元編程能力,這一特性足以讓開發者們腦洞大開。
關於ES2016的最重磅的消息莫過於11月初es標準委員會宣布將Object.observe從ES2016草案中移除了,儘管它已經是stage2幾乎已經是事實標準。官方給出的解釋是,這3年的時間前端世界變化實在太大,社區已經有了一些更優秀簡潔的實現了(polymer的observe-js),而且React帶來的immutable object在社區的流行使得基於可變數據的Object.observe的處境變的尷尬,O.o再繼續下去的意義不大了。
除此之外,ES2016的相關草案也已經確定了一大部分其他new features。這裡提兩個我比較感興趣的new feature:
  1. async/awai
    寫過C#的同學應該對這兩個關鍵字很熟悉了,async/await是為了更優雅的異步編程做的一個關鍵字級別的封裝,術語叫協程。 ES2016中async/await 實際是對Generator&Promise的上層封裝,幾乎同步的寫法寫異步比Promise更優雅更簡單,非常值得期待。
  2. decorator
    字面意思是裝飾器,其實等同於Java裡面的註解。註解機制對於大型應用的開發的作用想必不用我過多贅述了。用過的同學都說好。
目前ES2015/ES2016都有了比較優秀的轉譯器支持(沒錯我說的是babel),但是也不是all features supported,嚐新的過程中需要注意。
至於Typescript,你可以將它理解成加入了靜態類型的js的超集。不過我對於這種轉譯型語言一直不感冒(包括CoffeeScript),有興趣同學自己去了解下吧。

WebAssembly

WebAssembly選擇了跟ES2015在同一天發布,其項目領頭人是大名鼎鼎的js之父Brendan Eich。 WebAssembly旨在解決js作為解釋性語言的先天性能缺陷,試圖通過在瀏覽器底層加入編譯機制從而提高js性能。這個事情跟當時V8做的類似(有興趣的同學可以去了解下JIT),V8也因此一躍成為世界上跑的最快的js引擎。但是由於js是弱類型的動態語言,V8很快就觸碰到了性能優化的天花板,因為很多場景下還是免不了recompile的過程。因此WebAssembly索性將編譯過程前移(AOT)。 WebAssembly提供工具將各種語言轉換成特定的字節碼,瀏覽器直接面向字節碼編譯程序。其實在此之前,firefox已經搞過asm.js做類似的事情,只不過WebAssembly的方案更激進。有人認為WebAssembly可能是2016年最大的黑馬,如果wa能發展起來,若干年後我們看js編寫的應用會像現在看彙編語言寫出的大型程序的感覺。 WebAssembly項目目前由Apple、Google、Microsoft、Mozila四大瀏覽器廠商共同推進,還是非常值得期待的(寫不下去了我決定回去翻開我那本落灰的編譯原理。)。

Web Components

webcomponents規範起草於2013年,w3c標準委員會意圖提供一種瀏覽器級別的組件化解決方案,通過瀏覽器的原生支持定義一種標準化的組件開發方式。 webcomponents提出之際引發了整個前端圈的躁動,大家似乎在跨框架的組件化方案上看到了曙光。但是前端這圈子發展實在太特麼快了,在當前這個時間點,webcomponents也遭遇到了跟Object.observe相似的尷尬處境。我們先來看看webcomponents的幾個核心特性:
  1. Shadow DOM
  2. Custom Element
  3. Template Element
  4. HTML Imports
其中1、4現在都能很容易的通過自動化的工程手段解決了(shadow dom對應的是scoped css),而自定義標籤這種事情不論是React還是Angular這類組件框架都能輕鬆解決,那麼我用你webcomponents的理由呢?
另外webcomponents將目標對準的是HTML體系下的組件化,這一點跟React比就相對狹隘了(但是這並不表明React把戰線拉的那麼長就不會有問題)。
不過原生支持的跨框架的組件還是有存在的意義的,比如基礎組件庫,只是在當前來看web components發展還是有點營養不良。期待2016年能有實質上的突破吧。

沒有留言:

張貼留言