熱點(diǎn)推薦:2015前端生態(tài)發(fā)展回顧
處在2015年這個(gè)時(shí)間段來看,前端生態(tài)已經(jīng)進(jìn)入了第三階段??瓷先ズ孟褚呀?jīng)走的挺遠(yuǎn)了,實(shí)則不然。如果再用人類歷史上的三次工業(yè)革命來類比,前端 發(fā)展其實(shí)不過剛剛邁入了蒸汽機(jī)時(shí)代,開始逐步用工具來替代過往相當(dāng)一部分的人肉作業(yè),但是離電氣時(shí)代的自動(dòng)化流水線作業(yè)還有很長(zhǎng)一段路要走?;仡櫼幌?2015年前端的生態(tài)發(fā)展,我大致整理了幾個(gè)我覺得比較有歷史意義的事件。
按時(shí)間順序:
-
年初 React Native 的發(fā)布,引領(lǐng) React 正式走上歷史舞臺(tái)。
-
3月 angular2.0 第一個(gè)預(yù)覽版發(fā)布
-
5月 http/2.0 標(biāo)準(zhǔn)正式發(fā)布,同月 iojs 與 nodejs合并。
-
6月 ES6 和 WebAssembly 落地
-
7月 迄今為止React生態(tài)圈影響最大的Flux實(shí)現(xiàn)redux發(fā)布1.0版本
-
8月 Facebook公開了在React上應(yīng)用GraphQL的relay框架的技術(shù)預(yù)覽版
-
9月 React Native for Andriod 發(fā)布
-
11月伊始,es標(biāo)準(zhǔn)委員會(huì)宣布將歷時(shí)3年研究的Object.observe從草案中移除,盡管它原本已經(jīng)是stage2,幾乎已經(jīng)是ES7的 事實(shí)標(biāo)準(zhǔn)。雙十一剛一結(jié)束,阿里手淘團(tuán)隊(duì)發(fā)布了名為 無線電商動(dòng)態(tài)化解決方案 的 Weex,也有人給了它一個(gè)更具象的名字,vue native。
-
12月,趕在2015的尾巴,aurelia和angular2先后發(fā)布beta版。
css方面,postcss & cssnext先后高調(diào)走到臺(tái)前。
觀念的變化
由于近幾年前端的野蠻生長(zhǎng)以及前端應(yīng)用的多元化和復(fù)雜化,整個(gè)技術(shù)形態(tài)已經(jīng)跟幾年前純做頁面的時(shí)代完全迥異了。主要觀念的變化總結(jié)來看在于一點(diǎn),現(xiàn)在的前端開發(fā)面向的是web app而不是web page。 今天的前端開發(fā)模式跟傳統(tǒng)的GUI軟件(如C++、.NET開發(fā)的windows客戶端)已經(jīng)很接近了,而且由于現(xiàn)在前端領(lǐng)域?yàn)榱私鉀Q日益復(fù)雜的web業(yè) 務(wù)需求及體量,越來越多的借鑒了傳統(tǒng)客戶端的開發(fā)經(jīng)驗(yàn),導(dǎo)致兩者變得越來越趨同。再加上前端一些獨(dú)特的特性(免安裝、增量安裝等),工程上的復(fù)雜度有過之 而無不及。前端如今已經(jīng)脫離了茹毛飲血、刀耕火種的原始社會(huì),開始步入了工業(yè)時(shí)代。
框架 & 類庫的變化
今年最火的框架/類庫毫無疑問當(dāng)屬React了。React從2014年年中開始廣泛受到開發(fā)者關(guān)注,但是真正開始在社區(qū)獨(dú)領(lǐng)風(fēng)騷還得歸功于 2015年初React Native的發(fā)布。React Native的發(fā)布使得js統(tǒng)一三端(前端、后端、移動(dòng)端)開發(fā)成為可能(現(xiàn)在這個(gè)時(shí)間點(diǎn)看可能還是過于理想,但是整體方向還是對(duì)的),這一針強(qiáng)心劑吸引 了大量開發(fā)者的眼球。筆者對(duì)此最大的感受就是,我在社區(qū)發(fā)表一篇react的入門教程級(jí)別的軟文便可獲得廣泛關(guān)注及轉(zhuǎn)發(fā),相應(yīng)的寫angular源碼剖析 的準(zhǔn)干貨大部分情況則是門可羅雀。
我們挑幾個(gè)主流的框架來講講這一層的變化。
React & Redux
React基本簡(jiǎn)介可以參考這篇文章React簡(jiǎn)介,這里不再贅述。這里挑幾個(gè)核心特征簡(jiǎn)單來講:
-
virtual dom
這個(gè)可以說是F家工程師超強(qiáng)工程能力的最佳體現(xiàn)了(Relay也算一個(gè)),從本質(zhì)來看它是通過用js object來模擬了一個(gè)dom tree,然后將這層virtual dom插在react組件跟真實(shí)dom之間,配合強(qiáng)勁的dom diff算法實(shí)現(xiàn)它一直標(biāo)榜的高性能。 -
jsx
同樣為了配合react中的組件化開發(fā)模式,F(xiàn)家發(fā)明了一套新的語法jsx。乍看之下它像是html in js,這也是初接觸的開發(fā)者最難以接受的,典型的違背前端推崇多年的表現(xiàn)與業(yè)務(wù)分離的原則啊。其實(shí)這里要換個(gè)角度來看jsx,它并不是html in js,準(zhǔn)確來說它是一個(gè)用來構(gòu)建react組件樹的AST。這樣來想你就能理解react中這一看似怪異的設(shè)計(jì)了。 -
immutable object
不可變對(duì)象是函數(shù)式編程中的重要概念,react的介入使得這一理念在前端社區(qū)中流行起來。從目前各種類庫的實(shí)現(xiàn)來看,不可變對(duì)象在大型應(yīng)用中擁有傳統(tǒng)可 變對(duì)象不具備的優(yōu)勢(shì)。尤其在這個(gè)內(nèi)存不值錢的年代。從目前immutable object的良好走勢(shì)來看,將來有可能被es納入規(guī)范之中。目前可以通過facebook的immutable.js來實(shí)現(xiàn)。
Redux則是目前react配套的Flux模式的各種實(shí)現(xiàn)(其實(shí)現(xiàn)在兩者的關(guān)系越來越模糊了)中最火的一個(gè),在此基礎(chǔ)上它引入了函數(shù)式編程、單一 數(shù)據(jù)源、不可變數(shù)據(jù)、中間件等概念。一定程度來講,redux是今年react生態(tài)甚至整個(gè)前端生態(tài)中影響最大的一個(gè)框架,它給整個(gè)前端技術(shù)棧引入了很多 新成員,盡管這些概念可能在其他領(lǐng)域已經(jīng)有了廣泛的應(yīng)用。雖然它們是否會(huì)在大規(guī)模的應(yīng)用實(shí)踐中被廣大開發(fā)者認(rèn)可還需要再檢驗(yàn),但至少給我們帶來了一些新的 思路。其中的單一數(shù)據(jù)源、不可變數(shù)據(jù)、中間件等思路目前來看還是非常有價(jià)值的,尤其是單一數(shù)據(jù)源跟不可變數(shù)據(jù),很有可能在將來成為大型應(yīng)用架構(gòu)中的標(biāo)配 (目前來看至少在應(yīng)用中構(gòu)建Store層在當(dāng)前的前端架構(gòu)中是勢(shì)在必行的)。單一數(shù)據(jù)源就好比在前端構(gòu)建了一個(gè)集中式數(shù)據(jù)庫,所有的數(shù)據(jù)存取操作對(duì)象都是 它,不單如此它里面還實(shí)現(xiàn)了觸發(fā)器,當(dāng)有insert/update操作時(shí)它會(huì)對(duì)相應(yīng)組件作rerender動(dòng)作,這個(gè)在各組件之間有數(shù)據(jù)同步需求的場(chǎng)景 下就非常有用了。
至于我對(duì)函數(shù)式編程的看法,后面單獨(dú)闡述。
在我看來,react的優(yōu)勢(shì)并不在組件化,組件化的實(shí)現(xiàn)方案多種多樣。react的優(yōu)勢(shì)在于virtual dom及一個(gè)幾乎構(gòu)成閉環(huán)的強(qiáng)大生態(tài),這歸功于F家工程師強(qiáng)大的工程能力跟架構(gòu)能力。virtual dom將應(yīng)用表現(xiàn)層從瀏覽器這個(gè)基于dom的上下文中抽離出來,通過原生js對(duì)象模型的方式使得react具備在任何環(huán)境支撐上層表現(xiàn)的能力。上層的渲染 引擎可以是canvas、native、服務(wù)端甚至是桌面端,只要相應(yīng)的端提供基于react組件的渲染能力,即可達(dá)到一套代碼、或者只要很少的改動(dòng)就能 移植到任一終端環(huán)境的效果,這個(gè)就非??鋸埩?。react從0.14版本之后便將react-dom抽出來變成一個(gè)獨(dú)立的庫,可見react的野心并不局 限于瀏覽器,相反從這點(diǎn)來看,react反而是受到了dom的掣肘。
Angular2 & Vue.js
ng2跟ng1相比是一個(gè)完全革命性版本而不是升級(jí)版,它是一個(gè)為了迎合未來的標(biāo)準(zhǔn)及理念來設(shè)計(jì)的全新框架,而這些新的理念又無法通過改進(jìn) ng1.x的方式來實(shí)施,所以angular團(tuán)隊(duì)做了這么一個(gè)看似激進(jìn)的決策,可以理解成重構(gòu)已經(jīng)無法滿足需求只能重寫了。ng2也采用純組件化的開發(fā)思 路,任何單元對(duì)于它來說都是組件。同時(shí),ng2里面也引入了一些全新的概念(對(duì)于前端而言)來提升框架的性能及設(shè)計(jì),例如基于worker的數(shù)據(jù)檢測(cè)機(jī)制 能大幅度提升渲染性能(對(duì)應(yīng)實(shí)現(xiàn)是zone.js),基于響應(yīng)式編程的新的編程模型能更大的改善編碼體驗(yàn)(對(duì)應(yīng)實(shí)現(xiàn)RxJS)。趕在2015年的尾 巴,ng2正式發(fā)布beta版,對(duì)于angular的這次自我革命是否能成功,還有待后續(xù)檢驗(yàn)。另外原angular團(tuán)隊(duì)中出來的一個(gè)成員開發(fā)了一個(gè)類 ng2的框架aurelia,有相當(dāng)?shù)拈_發(fā)者認(rèn)為它更配稱為ng2,值得關(guān)注。
由于阿里在背后的技術(shù)實(shí)踐及支持,Vue.js今年也開始得到越來越多的關(guān)注。vue相對(duì)于angular1.x的優(yōu)勢(shì)在于輕量、易用、更優(yōu)異的性能及面向組件化的設(shè)計(jì),目前發(fā)展態(tài)勢(shì)也非常好,是移動(dòng)端開發(fā)的一個(gè)重要技術(shù)選型之一。
標(biāo)準(zhǔn) & 語言的變化
現(xiàn)在回顧起來,2015年真的是很有意義的一年:這一年是Web的25歲生日,也是js的20歲生日。同時(shí)又是ES6標(biāo)準(zhǔn)落地的一年。ES6是迄今 為止ECMAScript標(biāo)準(zhǔn)最大的變革(如果不算上胎死腹中的ES4的話),帶來了一系列令開發(fā)者興奮的新特性。從目前es的進(jìn)化速度來看,es后面應(yīng) 該會(huì)變成一個(gè)個(gè)的feature發(fā)布而不是像以前那樣大版本號(hào)的方式,所以現(xiàn)在官方也在推薦 ES+年份 這種叫法而不是 ES +版本。
ES2015(ES6) & ES2016(ES7) & TypeScript
6月中ES2015規(guī)范正式發(fā)布,從ES2015帶來的這些革命性的新語法來看,JS從此具備了用于開發(fā)大型應(yīng)用的語言的基本要素:原生的 mudule支持、原生的class關(guān)鍵字、更簡(jiǎn)潔的api及語法糖,更穩(wěn)定的數(shù)據(jù)類型。而這些new features中,有幾個(gè)我認(rèn)為是會(huì)影響整個(gè)前端發(fā)展進(jìn)程的:
-
Module & Module Loader
ES2015中加入的原生模塊機(jī)制支持可謂是意義最重大的feature了,且不說目前市面上五花八門的module/loader庫,各種不同實(shí)現(xiàn)機(jī)制 互不兼容也就罷了(其實(shí)這也是非常大的問題),關(guān)鍵是那些模塊定義/裝載 語法都丑到爆炸,但是這也是無奈之舉,在沒有語言級(jí)別的支持下,js只能做到這一步,正所謂巧婦難為無米之炊。ES2016中的Module機(jī)制借鑒自 CommonJS,同時(shí)又提供了更優(yōu)雅的關(guān)鍵字及語法(當(dāng)然也存在一些問題)。遺憾的是同樣有重大價(jià)值的Module Loader在2014年底從ES2015草案中移除了,我猜測(cè)可能是對(duì)于瀏覽器而言Module Loader的支持遭遇了一些技術(shù)上的難點(diǎn),從而暫時(shí)性的舍棄了這一feature。但是一個(gè)原生支持的模塊加載器是非常有意義的,相信它不久后還是會(huì)回 歸到ES規(guī)范中(目前由WHATWG組織在單獨(dú)維護(hù))。 -
Class
準(zhǔn)確來說class關(guān)鍵字只是一個(gè)js里構(gòu)造函數(shù)的語法糖而已,跟直接function寫法無本質(zhì)區(qū)別。只不過有了Class的原生支持后,js的面向?qū)ο髾C(jī)制有了更多的可能性,比如衍生的extends關(guān)鍵字(雖然也只是語法糖)。 -
Promise & Reflect API
Promise的誕生其實(shí)已經(jīng)有幾十年了,它被納入ES規(guī)范最大意義在于,它將市面上各種異步實(shí)現(xiàn)庫的最佳實(shí)踐都標(biāo)準(zhǔn)化了。至于Reflect API,它讓js歷史上第一次具備了元編程能力,這一特性足以讓開發(fā)者們腦洞大開。
關(guān)于ES2016的最重磅的消息莫過于11月初es標(biāo)準(zhǔn)委員會(huì)宣布將Object.observe從ES2016草案中移除了,盡管它已經(jīng)是 stage2幾乎已經(jīng)是事實(shí)標(biāo)準(zhǔn)。官方給出的解釋是,這3年的時(shí)間前端世界變化實(shí)在太大,社區(qū)已經(jīng)有了一些更優(yōu)秀簡(jiǎn)潔的實(shí)現(xiàn)了(polymer的 observe-js),而且React帶來的immutable object在社區(qū)的流行使得基于可變數(shù)據(jù)的Object.observe的處境變的尷尬,O.o再繼續(xù)下去的意義不大了。
除此之外,ES2016的相關(guān)草案也已經(jīng)確定了一大部分其他new features。這里提兩個(gè)我比較感興趣的new feature:
-
async/await
寫過C#的同學(xué)應(yīng)該對(duì)這兩個(gè)關(guān)鍵字很熟悉了,async/await是為了更優(yōu)雅的異步編程做的一個(gè)關(guān)鍵字級(jí)別的封裝,術(shù)語叫協(xié)程。ES2016中 async/await 實(shí)際是對(duì)Promise的上層封裝,幾乎同步的寫法寫異步比Promise更優(yōu)雅更簡(jiǎn)單,非常值得期待。 -
decorator
字面意思是裝飾器,其實(shí)等同于Java里面的注解。注解機(jī)制對(duì)于大型應(yīng)用的開發(fā)的作用想必不用我過多贅述了。用過的同學(xué)都說好。
目前ES2015/ES2016都有了比較優(yōu)秀的轉(zhuǎn)譯器支持(沒錯(cuò)我說的是babel),但是也不是all features supported,嘗新的過程中需要注意。
至于Typescript,你可以將它理解成加入了靜態(tài)類型的js的超集。不過我對(duì)于這種轉(zhuǎn)譯型語言一直不感冒(包括快死掉的CoffeeScript),有興趣同學(xué)自己去了解下吧。。
WebAssembly
WebAssembly選擇了跟ES2015在同一天發(fā)布,其項(xiàng)目領(lǐng)頭人是大名鼎鼎的js之父Brendan Eich。WebAssembly旨在解決js作為解釋性語言的先天性能缺陷,試圖通過在瀏覽器底層加入編譯機(jī)制從而提高js性能。這個(gè)事情跟當(dāng)時(shí)V8做 的類似(有興趣的同學(xué)可以去了解下JIT),V8也因此一躍成為世界上跑的最快的js引擎。但是由于js是弱類型的動(dòng)態(tài)語言,V8很快就觸碰到了性能優(yōu)化 的天花板,因?yàn)楹芏鄨?chǎng)景下還是免不了recompile的過程。WebAssembly提供工具將各種語言轉(zhuǎn)換成特定的字節(jié)碼,瀏覽器直接面向字節(jié)碼編譯 程序。其實(shí)在此之前,firefox已經(jīng)搞過asm.js做類似的事情,只不過WebAssembly的方案更激進(jìn)。有人認(rèn)為WebAssembly可能 是2016年最大的黑馬,如果wa能發(fā)展起來,若干年后我們看js編寫的應(yīng)用會(huì)像現(xiàn)在看匯編語言寫出的大型程序的感覺。WebAssembly項(xiàng)目目前由 蘋果、谷歌、微軟、Mozila四大瀏覽器廠商共同推進(jìn),還是非常值得期待的(寫不下去了我決定回去翻開我那本落灰的編譯原理。。)。
Web Components
webcomponents規(guī)范起草于2013年,w3c標(biāo)準(zhǔn)委員會(huì)意圖提供一種瀏覽器級(jí)別的組件化解決方案,通過瀏覽器的原生支持定義一種標(biāo)準(zhǔn)化 的組件開發(fā)方式。webcomponents提出之際引發(fā)了整個(gè)前端圈的躁動(dòng),大家似乎在跨框架的組件化方案上看到了曙光。但是前端這圈子發(fā)展實(shí)在太特么 快了,在當(dāng)前這個(gè)時(shí)間點(diǎn),webcomponents也遭遇到了跟Object.observe相似的尷尬處境。我們先來看看webcomponents 的幾個(gè)核心特性:
-
Shadow DOM
-
Custom Element
-
Template Element
-
HTML Imports
其中1、4現(xiàn)在都能很容易的通過自動(dòng)化的工程手段解決了(shadow dom對(duì)應(yīng)的是scoped css),而自定義標(biāo)簽這種事情不論是React還是Angular這類組件框架都能輕松解決,那么我用你webcomponents的理由呢?
另外webcomponents將目標(biāo)對(duì)準(zhǔn)的是HTML體系下的組件化,這一點(diǎn)跟React比就相對(duì)狹隘了(但是這并不表明React把戰(zhàn)線拉的那么長(zhǎng)就不會(huì)有問題)。
不過原生支持的跨框架的組件還是有存在的意義的,比如基礎(chǔ)組件庫,只是在當(dāng)前來看web components發(fā)展還是有點(diǎn)營(yíng)養(yǎng)不良。期待2016年能有實(shí)質(zhì)上的突破吧。
架構(gòu)的變化
2015年出現(xiàn)的新的技術(shù)及思路,影響最大的就是技術(shù)選型及架構(gòu)了。我們可以從下面幾點(diǎn)來看看它對(duì)前端架構(gòu)上都有哪些影響。
組件化
React的風(fēng)靡使得組件化的開發(fā)模式越來越被廣大開發(fā)者關(guān)注。首先要肯定的是,組件化是一個(gè)非常值得去做的事情,它在工程上會(huì)大大提升項(xiàng)目的可維 護(hù)性及拓展性,同時(shí)會(huì)帶來一些代碼可復(fù)用的附加效果。但這里要強(qiáng)調(diào)的一點(diǎn)是,組件化的指導(dǎo)策略一定是分治(分而治之)而不是復(fù)用,分治的目的是為了使得組 件之間解耦跟正交,從而提高可維護(hù)性及多人協(xié)同開發(fā)效率。如果以復(fù)用為指導(dǎo)原則那么組件最后一定會(huì)發(fā)展到一個(gè)配置繁雜代碼臃腫的狀態(tài)。如果以組件的形態(tài)劃 分,可以分為兩個(gè)類型:基礎(chǔ)控件和業(yè)務(wù)組件?;A(chǔ)控件不應(yīng)包含業(yè)務(wù)邏輯不然達(dá)不到拿來即用的效果,因此它也會(huì)表現(xiàn)出可復(fù)用的價(jià)值,但是根本還是為了提高業(yè) 務(wù)組件的可維護(hù)性。至于業(yè)務(wù)組件,可復(fù)用的價(jià)值就很低了。
-
組件化指的是什么
組件化這個(gè)詞,在UI這一層通常指“標(biāo)簽化”,也就是把大塊的業(yè)務(wù)界面,拆分成若干小塊,然后進(jìn)行組裝。
狹義的組件化一般是指標(biāo)簽化,也就是以自定義標(biāo)簽(自定義屬性)為核心的機(jī)制。這也是我們通常認(rèn)識(shí)的組件。
廣義的組件化包括對(duì)數(shù)據(jù)邏輯層業(yè)務(wù)梳理,形成不同層級(jí)的能力封裝。它不一定是一個(gè)自定義語義標(biāo)簽:它可以是一個(gè)包含邏輯(js)、樣式 (css)、模版(html)的功能完備的結(jié)構(gòu)單元,也就是我們常“口口相傳”的模塊(從術(shù)語準(zhǔn)確性的角度來看模塊這個(gè)描述并不合適,應(yīng)該稱之為組件); 它也可以是一個(gè)單純的js,比如http組件這種純邏輯單元。嚴(yán)格從概念上來講,css跟html是不具備單獨(dú)/組合成一個(gè)組件的,它們不具備描述邏輯的 能力(非圖靈完備)。從這個(gè)層面來看,全組件化是沒有任何問題及疑義的。 -
是否需要全組件化
我們通常說的組件指的是狹義上的組件,而且往往我們理解的全組件化也是建立在狹義的組件基礎(chǔ)上的,
代表框架是React。React+Flux體系下,它提倡盡可能將頁面作細(xì)粒度的組件拆分,組件的數(shù)據(jù)全部由父級(jí)組件通過props傳遞而來。這本身是 一件非常有價(jià)值的事情,能有效的確保應(yīng)用狀態(tài)的穩(wěn)定及可預(yù)測(cè)性,但是應(yīng)用一旦復(fù)雜龐大起來,組件樹變得“枝繁葉茂”導(dǎo)致葉子節(jié)點(diǎn)層級(jí)過深,當(dāng)出現(xiàn)數(shù)據(jù)問題 時(shí),我們必須一層層的回溯來定位bug。而且組件樹過于龐大也會(huì)增加組件之間的通訊負(fù)擔(dān)。從狹義的組件來看,我對(duì)全組件化是存懷疑態(tài)度的,工程上的成本太 高是最大的問題,而且大部分開發(fā)者很難拿捏合適的組件粒度,容易出現(xiàn)過細(xì)/過粗的拆分。很多場(chǎng)景其實(shí)并不適合實(shí)現(xiàn)成狹義上的組件,它以零散的模板的方式存 在更合適。
但是如果從廣義的組件來看,全組件的意義是很大的,我們需要通過拆分頁面邏輯區(qū)塊的方式實(shí)現(xiàn)程序的解耦,從而提升應(yīng)用的可維護(hù)性。
綜合來看,我覺得工程上更具可行的全組件化方案應(yīng)該是:細(xì)粒度的基礎(chǔ)組件庫 + 粗粒度的模板/組件。
工程化
工程化是近年前端提到最多的問題之一,而且個(gè)人認(rèn)為是當(dāng)前前端發(fā)展階段最有價(jià)值的問題,也是前端開發(fā)通往工業(yè)化時(shí)代的必經(jīng)之路。這里不贅述,有興趣的同學(xué)看我前陣子整理的一篇文章前端工程化知識(shí)點(diǎn)回顧
應(yīng)用架構(gòu)層 MVVM & Flux
MVVM想必大部分前端都耳熟能詳了,代表框架是angular、vue、avalon。angular在1.2版本之后加入了 controllerAs語法,使得controller可以變成一個(gè)真正意義上的VM,angular整個(gè)架構(gòu)也才真正能稱之為嚴(yán)格的MVVM(之前只 能說是帶有雙向綁定的MVC/MVP)。
Flux是facebook隨React一并推出的新的(準(zhǔn)確來說其實(shí)是改進(jìn)的,并非原創(chuàng))架構(gòu)模型,核心概念是單向數(shù)據(jù)流。Flux實(shí)質(zhì)上就是一個(gè)演進(jìn) 版的中介者模式,不同的是它同時(shí)包裝了action、store、dispatcher、view等概念。關(guān)于Flux對(duì)應(yīng)用分層、數(shù)據(jù)在不同層之間只能 單向流轉(zhuǎn)的方式我是很贊成的。應(yīng)用的分層在業(yè)務(wù)稍復(fù)雜的應(yīng)用中都是很有必要的,它更利于應(yīng)用的伸縮及拓展,副作用是會(huì)帶來一定的復(fù)雜度(在我看來這點(diǎn)復(fù)雜 度根本就可以忽略不計(jì))。
今年被黑的最多的前端主流框架莫過于angular了。老實(shí)講前端圈真的挺善變的,去年各種大會(huì)都在分享angular黑jquery,今年就變成了都在分享react黑angular了。黑的點(diǎn)大致有三:
-
angular的部分實(shí)現(xiàn)太low
-
太多Java身上帶來的臭毛病(并沒有在黑Java)
-
mvvm自身的缺陷
第一點(diǎn)第二點(diǎn)我并無異議。angular的臟值檢測(cè)機(jī)制相對(duì)于其他mvvm框架的雙向綁定實(shí)現(xiàn)方式確實(shí)不太優(yōu)雅,同樣有硬傷的還有失敗的模塊語法及過多過于復(fù)雜的概念。但是對(duì)于第三點(diǎn),我有不同的看法。
大多數(shù)人黑mvvm會(huì)以Facebook那張經(jīng)典的flux vs mvc的圖為論據(jù),對(duì)于雙向綁定造成的數(shù)據(jù)流紊亂及應(yīng)用狀態(tài)的不確定導(dǎo)致問題定位困難的觀點(diǎn)我是認(rèn)同的,這一點(diǎn)我也有切身體會(huì),但是單純的這一點(diǎn)就足以否定mvvm么?就說flux比mvvm高明?
MVVM在富表格型(自造的詞 ) 應(yīng)用開發(fā)效率上是高于Flux的,典型的就是一些后臺(tái)管控平臺(tái)。而且最重要的是,MVVM跟Flux并不互斥,我們?cè)贛VVM中照樣可以引入Flux中的 一些機(jī)制從而確保應(yīng)用狀態(tài)的穩(wěn)定。很多時(shí)候我們對(duì)于框架/架構(gòu)的孰優(yōu)孰劣的爭(zhēng)論是沒意義的,拋開業(yè)務(wù)場(chǎng)景談解決方案都是耍流氓。
業(yè)務(wù)數(shù)據(jù)層 Relay & falcor
這一層對(duì)大部分前端來說可能是比較新的概念,其實(shí)我們可以這樣理解:在一個(gè)完整的應(yīng)用中,業(yè)務(wù)數(shù)據(jù)層指的就是數(shù)據(jù)來源,在angular體系中可以等同于ngResource模塊(準(zhǔn)確來說應(yīng)該是$http)。
Relay是f家推出的在react上應(yīng)用GraphQL的框架,它的大致思路是:前端通過在應(yīng)用中定義一系列的schema來聲明需要的接口數(shù)據(jù)結(jié)構(gòu), 后端配合GraphQL引擎返回相應(yīng)的數(shù)據(jù)。整個(gè)事情對(duì)于前端來說意義簡(jiǎn)直是跨時(shí)代的,工業(yè)化典范!不僅能極大提升前后端協(xié)同的開發(fā)效率,還能增加前端對(duì) 于應(yīng)用完整的掌控力。但是目前來看問題就是實(shí)施過于復(fù)雜,而且還得后端服務(wù)支持,工程成本太高,這一點(diǎn)上Meteor顯然做的更好。
falcor則是Netflix出品的一個(gè)數(shù)據(jù)拉取庫,核心理念是單一數(shù)據(jù)源,跟Redux的單store概念一致。用法跟Realy類似,也需要前端定義數(shù)據(jù)schema。
另外還有一個(gè)新的W3C標(biāo)準(zhǔn)api:fetch,它的級(jí)別等同于XMLHttpRequest,旨在提供比ajax更優(yōu)雅的資源獲取方式,目前幾個(gè)主流瀏覽器支持的都還不錯(cuò),也有官方維護(hù)的polyfill,幾乎可以確定是未來的主流數(shù)據(jù)請(qǐng)求api。
業(yè)務(wù)數(shù)據(jù)層是前端應(yīng)用中比較新的概念,它的多元化主要會(huì)影響到應(yīng)用的架構(gòu)設(shè)計(jì),這里不細(xì)講后面再來說。
新的編程范式
函數(shù)式編程(FP)
函數(shù)式編程(functional programming)是近年比較火爆的一個(gè)編程范式,F(xiàn)P基于lambda演算,與以圖靈機(jī)為基礎(chǔ)的指令式編程(Java、C++)有著明顯的差異。 lambda演算更關(guān)注輸入輸出,更符合自然行為場(chǎng)景,所以看上去更適合事件驅(qū)動(dòng)的web體系,這點(diǎn)我也認(rèn)同。但問題是,太多開發(fā)者看到redux那么火 爆就急著學(xué)redux用js去玩函數(shù)式,我覺得這個(gè)有待商榷。js作為一個(gè)以基于函數(shù)(scheme,父親)跟基于對(duì)象(Self,母親)的編程語言為藍(lán) 本設(shè)計(jì)然后語法又靠近Java(隔壁老王)的“混血”語言,你非得用它去寫函數(shù)式,是不是過于一廂情愿?尤其是在現(xiàn)在瀏覽器還不支持尾調(diào)用優(yōu)化的情況下, 你讓那激增的調(diào)用??扇绾问呛?,如果你確實(shí)鐘情于函數(shù)式,可以去玩玩那些更functional的語言(Haskell、Clojure等),而不是從js入手。最近看到一個(gè)老外關(guān)于js 的函數(shù)式編程的看法,最后一句總結(jié)很精辟:Never forget that javascript hate you.
函數(shù)式響應(yīng)型編程(FRP)
函數(shù)式響應(yīng)型編程(functional reactive programming)不是一個(gè)新概念,但也不過是近兩年才引入到前端領(lǐng)域的,代表類庫就是ng2在用的rxjs。FRP關(guān)注的是事件及對(duì)應(yīng)的數(shù)據(jù)流, 你可以把它看作是一個(gè)基于事件總線(event bus)的觀察者模式,它主要適用于以GUI為核心的交互軟件中。但FRP最大的困難之處在于,如果你想使用這樣的編程范式,那么你的整個(gè)系統(tǒng)必須以 reactive為中心來規(guī)劃。目前微軟維護(hù)的ReactiveX項(xiàng)目已經(jīng)有各種語言的實(shí)現(xiàn)版本,有興趣的同學(xué)可以去了解下。
工具鏈的變化
去年最主流的前端構(gòu)建工具還是grunt&gulp,2015年隨著react的崛起和web標(biāo)準(zhǔn)的快速推進(jìn),一切又有了新的變化。
webpack & browserify & jspm
webpack跟browserify本質(zhì)上都是module bundler,差異點(diǎn)在于webpack提供更強(qiáng)大的loader機(jī)制讓其更變得更加靈活。當(dāng)然,webpack的流行自然還是離不開背后的react 跟facebook(可見有個(gè)強(qiáng)大的干爹多么重要)。但是從現(xiàn)在HTTP/2標(biāo)準(zhǔn)的應(yīng)用及實(shí)施進(jìn)展來看,webpack/browserify這種基于 bundle的打包工具也面臨著被歷史車輪碾過的危機(jī),相對(duì)的基于module loader的jspm反而更具前景(雖然現(xiàn)在使用前兩者的開發(fā)者都多于jspm)。
PostCSS & cssnext
PostCSS作為新一代的css處理器大有取Sass/Less而代之的趨勢(shì),Bootstrap v5也有著基于PostCSS去開發(fā)的計(jì)劃。但從本質(zhì)來講它又不算一個(gè)處理器,它更像是一個(gè)插件平臺(tái),能通過配置各種插件從而實(shí)現(xiàn)預(yù)處理器跟后處理器的效果。
cssnext官方口號(hào)是“使用來自未來的語法開發(fā)css,就在今天!”,但是cssnext又不是css4,它是一個(gè)能讓開發(fā)者現(xiàn)在就享受最新的css語法(包括自定義屬性、css變量等)的轉(zhuǎn)換工具。這一塊筆者還沒有過具體實(shí)踐,暫不多言。
寫在最后
從前端的發(fā)展現(xiàn)狀來看,未來理想的前端技術(shù)架構(gòu)應(yīng)該是每一層都是可組裝的,框架這種重型組合的適用場(chǎng)景會(huì)越來越局限。原因在于各部件不可拆卸會(huì)增加 架構(gòu)的升級(jí)代價(jià)同時(shí)會(huì)限制應(yīng)用的靈活性。舉個(gè)例子,我有一套面向pc端的后臺(tái)管控平臺(tái)的架構(gòu),view層采用angular開發(fā),哪天我要遷移到移動(dòng)端 來,angular性能不行啊,我換成vue就好了。哪天覺得ajax的寫法太挫,把http層替換成fetch就好了。又有一天后端的GranphQL 平臺(tái)搭好了,我把ngResource換成relay就OK了。
這種理想的方式當(dāng)然是完全正確的方向,但是目前來看它對(duì) 開發(fā)者/架構(gòu)師 的要求還是太高,工業(yè)級(jí)別上一套帶有約束性的框架還是有相當(dāng)?shù)男枨蟮?特別是當(dāng)團(tuán)隊(duì)開發(fā)者的水平良莠不齊時(shí)。當(dāng)然我覺得更正確的方式是流程上有一套完整的 自動(dòng)化方案用于確保團(tuán)隊(duì)提交的代碼質(zhì)量,只是目前基于動(dòng)態(tài)分析的代碼質(zhì)量檢測(cè)工具還沒有出現(xiàn),而且估計(jì)很長(zhǎng)一段時(shí)間內(nèi)都不會(huì)有)。雖然美好但是組合的方式 也不是沒有問題,各種五花八門的搭配容易造成社區(qū)的分化跟內(nèi)耗,一定程度上不利于整個(gè)生態(tài)圈的發(fā)展。
近年前端生態(tài)的野蠻發(fā)展影響最大的應(yīng)該就是新產(chǎn)品的技術(shù)選型了,亂花迷人眼,我們很難設(shè)計(jì)出一套適應(yīng)大部分場(chǎng)景、而且短時(shí)間內(nèi)不會(huì)被淘汰的架構(gòu)。前 端的變化太快通常會(huì)導(dǎo)致一些技術(shù)決策的反復(fù),今天的最佳實(shí)踐很可能明天就被視為反模式。難道最合適的態(tài)度是各種保留各種觀望,以不變應(yīng)萬變?在這一點(diǎn)上即 使如我這般在技術(shù)上一向激進(jìn)的人都有點(diǎn)畏手畏腳了。那句話怎么說的來著?從來沒有哪個(gè)圈子像今天的前端一樣混亂又欣欣向榮了。有人說2015年或許是大前 端時(shí)代的元年,目前看來,如果不是2015,那么它也一定會(huì)是2016年。
最后引用計(jì)子winter的一句話作為結(jié)語吧:
前端一直是一個(gè)變化很快的職能,它太年輕,年輕意味著可能性和機(jī)會(huì),也意味著不成熟和痛苦。我經(jīng)常擔(dān)心的事情就是,很可能走到最后,我們會(huì)發(fā)現(xiàn),我們做了很多,卻還是一無所獲。所幸至今回顧,每年還是總有點(diǎn)不同,也算給行業(yè)貢獻(xiàn)了些經(jīng)驗(yàn)值吧。
本文轉(zhuǎn)載自:https://github.com/kuitos/kuitos.github.io/issues/32