JavaScript寶座:七大框架論劍
李松峰博客:http://www.cn-cuckoo.com/ |
一周前,Throne of JS大會(huì)在多倫多召開(kāi),這應(yīng)該是我參加過(guò)的最有料也最不一樣的一次大會(huì)。大會(huì)官網(wǎng)如是說(shuō):
加載整個(gè)頁(yè)面,然后再“漸進(jìn)增強(qiáng)”以添加動(dòng)態(tài)行為,這種構(gòu)建Web應(yīng)用的方式已經(jīng)不夠好了。要想讓?xiě)?yīng)用加載快,反應(yīng)靈敏,而且又引領(lǐng)潮流,必須徹底檢討你的開(kāi)發(fā)手段。
這次大會(huì)邀請(qǐng)了七大JavaScript框架/庫(kù)的創(chuàng)建人,他們濟(jì)濟(jì)一堂,面對(duì)面交流各自的技術(shù)理念。所謂七大框架/庫(kù)分別是:AngularJS、Backbone、Batman、CanJS、Ember、Meteor、Knockout、Spine。
聲明:我在會(huì)上講Knockout,因此我的觀點(diǎn)顯然不是中立的。在這篇文章中,我重點(diǎn)討論這些創(chuàng)建人的思路和技術(shù)理念,盡量不提我贊成或反對(duì)什么。
沒(méi)錯(cuò),是8個(gè)框架,不是7個(gè)。但到底怎么回事兒,會(huì)議主辦方也沒(méi)有明確給我們解釋過(guò)……
文章可長(zhǎng)啦,先概述一下:
- 對(duì)許多Web開(kāi)發(fā)人員來(lái)說(shuō),要構(gòu)建富Web應(yīng)用,使用客戶(hù)端框架是理所當(dāng)然的。如果你什么框架也沒(méi)用,那要么你不是在做應(yīng)用,要么就會(huì)錯(cuò)過(guò)很多好東西。
- 在使用方法上,這些框架很多地方都是一致的(模型-視圖-*架構(gòu)、聲明綁定,等等——詳見(jiàn)下文) ,因此從某種意義講,無(wú)論你選擇哪一個(gè),都能得到同樣的好處。
- 理念上還是有不少差異,特別是在對(duì)框架和庫(kù)的看法上,分歧格外大。你的選擇會(huì)深刻影響你的架構(gòu)。
- 會(huì)議本身活潑,新穎,技術(shù)小組之間有很多交流和對(duì)話(huà)。我希望能有更多類(lèi)似的會(huì)議。
技術(shù):共識(shí)與分歧
隨著每個(gè)SPA(Single Page Application,單頁(yè)應(yīng)用)技術(shù)的逐一展示,一些相當(dāng)明顯的相似性和差異性浮出了水面。
共識(shí):漸進(jìn)增強(qiáng)不能建立真正的應(yīng)用
各技術(shù)門(mén)派一致認(rèn)為,真正的JavaScript應(yīng)用必須有適當(dāng)?shù)臄?shù)據(jù)模型,并具備客戶(hù)端渲染能力,而絕不僅僅是服務(wù)器處理數(shù)據(jù)再加上一些Ajax和jQuery代碼那么簡(jiǎn)單。
用Backbone創(chuàng)建人Jeremy Ashkenas的話(huà)說(shuō):“現(xiàn)如今,你說(shuō)‘單頁(yè)應(yīng)用’,都跟說(shuō)‘不用馬拉的車(chē)’差不多了”(意思是,早已經(jīng)沒(méi)那么新鮮了)2。
“不用馬拉的車(chē)”(horseless carriage)是汽車(chē)剛剛發(fā)明的時(shí)候,人們對(duì)它的稱(chēng)呼。——譯者注
共識(shí):模型-視圖-某某
所有技術(shù)門(mén)派都堅(jiān)持模型-視圖分離。有的強(qiáng)調(diào)MVC(Model View Control),有的提到MVVM(Model View ViewModel),甚至有人拒絕明確說(shuō)出第三個(gè)詞兒(只提模型、視圖,然后加上讓它們協(xié)調(diào)運(yùn)作的東西)。對(duì)各門(mén)派而言,最終結(jié)果其實(shí)是相似的。
共識(shí):推崇數(shù)據(jù)綁定
除了Backbone和Spine之外,其他框架都在自己的視圖里內(nèi)置了聲明數(shù)據(jù)綁定的機(jī)制(Backbone的設(shè)計(jì)理念強(qiáng)調(diào)讓用戶(hù)“自選視圖技術(shù)”)。
共識(shí):IE6已死
在小組討論中,大多數(shù)框架的創(chuàng)建者說(shuō),他們對(duì)IE瀏覽器的支持只限于7+(事實(shí)上,Ember和AngularJS的起點(diǎn)是IE8,Batman需要ES5“墊片”才能在IE9之前的IE版本中使用)。這也是大勢(shì)所趨:jQuery 2已經(jīng)不打算支持IE9以下的舊版本IE了。
只有Backbone和Knockout還堅(jiān)定支持IE6+(我不清楚Backbone的內(nèi)部實(shí)現(xiàn),但Knockout會(huì)把IE6/7那些令人抓狂的渲染及事件方面的怪異行為屏蔽掉)。
共識(shí):許可和源代碼控制
大家都使用MIT許可,并且托管在GitHub上。
分歧:庫(kù)與框架
這是目前最大的分歧。下表對(duì)JavaScript庫(kù)和框架進(jìn)行了歸類(lèi):
JavaScript庫(kù) |
JavaScript框架 |
---|---|
Backbone(9552) | Ember(3993) |
Knockout(2357) | AngularJS(2925) |
Spine(2017) | Batman(958) |
CanJS(321) | Meteor(4172)——了不起,見(jiàn)下文 |
*括號(hào)中的數(shù)字是最近某個(gè)時(shí)間點(diǎn)GitHub上的關(guān)注者數(shù)量,粗略地代表各自的影響力。
什么意思呢?
- JavaScript庫(kù),插到既有架構(gòu)中,補(bǔ)充特定功能。
- JavaScript框架,提供一個(gè)架構(gòu)(文件結(jié)構(gòu)啊,等等),你必須遵守它,只要你遵守,那剩下的就全都是處理通用需求了。
目前來(lái)看,鼓吹框架模型最賣(mài)力氣的是Ember,其創(chuàng)建人Yehuda Katz之前是(理念相似的)Rails和SproutCore項(xiàng)目的開(kāi)發(fā)者。他的觀點(diǎn)是,缺少任何組件都不夠給力,都不能說(shuō)是真正在推動(dòng)技術(shù)進(jìn)步。相反的觀點(diǎn)說(shuō),庫(kù)的目的更明確,因而更容易掌握、采用、定制,也有助于把項(xiàng)目風(fēng)險(xiǎn)降到最低,畢竟你的架構(gòu)不會(huì)嚴(yán)重依賴(lài)任何一個(gè)外部項(xiàng)目。根據(jù)我參加對(duì)話(huà)的情況看,現(xiàn)場(chǎng)觀眾也分成了兩派,有支持框架的,也有支持庫(kù)的。
請(qǐng)注意,AngularJS可以說(shuō)是介于庫(kù)和框架之間一種形態(tài):它不要求開(kāi)發(fā)時(shí)遵守特定的文件組織方式(與庫(kù)類(lèi)似),但在運(yùn)行時(shí),它提供一個(gè)“應(yīng)用生命周期”,可以對(duì)號(hào)入座地把代碼安排進(jìn)去(與框架類(lèi)似)。之所以把它歸入框架之列,是因?yàn)锳ngularJS團(tuán)隊(duì)樂(lè)于接受這個(gè)說(shuō)法。
分歧:靈活,還是整合
每個(gè)技術(shù)門(mén)派都有不同程度的強(qiáng)制性規(guī)定:
視圖 | URL路由 | 數(shù)據(jù)存儲(chǔ) | |
---|---|---|---|
AngularJS | 內(nèi)置基于DOM的模板(強(qiáng)制) | 內(nèi)置(可選) | 內(nèi)置系統(tǒng)(可選) |
Backbone | 自選(最常用的是基于字符串的模板庫(kù)handlebars.js) | 內(nèi)置(可選) | 內(nèi)置(可重寫(xiě)) |
Batman | 內(nèi)置基于DOM的模板(強(qiáng)制) | 內(nèi)置(強(qiáng)制) | 內(nèi)置系統(tǒng)(強(qiáng)制) |
CanJS | 內(nèi)置基于字符串的模板(強(qiáng)制) | 內(nèi)置(可選) | 內(nèi)置(可選) |
Ember | 內(nèi)置基于字符串的模板(強(qiáng)制) | 內(nèi)置(強(qiáng)制) | 內(nèi)置(可重寫(xiě)) |
Knockout | 內(nèi)置基于DOM的模板(可選,也可以用基于字符串的模板) | 自選(大都使用sammy.js或history.js) | 自選(如knockout.mapping或只用$.ajax) |
Meteor | 內(nèi)置基于字符串的模板(強(qiáng)制) | 內(nèi)置(強(qiáng)制?不確定) | 內(nèi)置(Mongo,強(qiáng)制) |
Spine | 自選基于字符串的模板 | 內(nèi)置(可選) | 內(nèi)置(可選?不確定) |
不難想見(jiàn),只要某個(gè)庫(kù)在某方面是開(kāi)放的,他們的人就會(huì)強(qiáng)調(diào)只有這樣才能從總體上確保跟第三方庫(kù)兼容。同樣,顯而易見(jiàn)的反對(duì)意見(jiàn)則是,只有內(nèi)置才能保證無(wú)縫整合。再次,根據(jù)我參加的對(duì)話(huà),現(xiàn)場(chǎng)觀眾也各持己見(jiàn),說(shuō)什么的都有,基本上可以看出每個(gè)人對(duì)其他技術(shù)組合的了解程度。
Ember的Tom Dale說(shuō):“我們加入了很多魔法,但都是有用的魔法,換句話(huà)說(shuō),它們可以分解為常規(guī)的操作原語(yǔ)。”
分歧:基于字符串的模板與基于DOM的模板
(請(qǐng)參考上面的表格。)對(duì)基于字符串的模板,大家?guī)缀醵歼x擇Handlebars.js作為模板引擎,它儼然成了這個(gè)領(lǐng)域的霸主,當(dāng)然CanJS用的是EJS。對(duì)基于字符串的模板,支持的人認(rèn)為“它更快”(不一定),而且“理論上,服務(wù)器也可以處理它”(也不一定,因?yàn)榍疤岜仨毷窃诜?wù)器上運(yùn)行所有模型代碼,而實(shí)踐中根本沒(méi)人那么做)。
而基于DOM的模板呢,意味著純粹通過(guò)在實(shí)際標(biāo)記中綁定來(lái)控制流程(each、if,等等),且不依賴(lài)任何外部模板庫(kù)。支持的聲音有“它更快”(不一定),另外“代碼易讀、易寫(xiě),且標(biāo)記與模板之間沒(méi)有隔閡,CSS如何與之交互也一目了然。”
在我看來(lái),最有吸引力的說(shuō)法來(lái)自AngularJS那幫家伙,他們認(rèn)為在不久的將來(lái),基于DOM的模板會(huì)得到瀏覽器原生支持。所以我們最好現(xiàn)在就用,從而可以輕松應(yīng)對(duì)未來(lái)。AngularJS來(lái)自Google,所以他們?cè)陂_(kāi)發(fā)Chromium時(shí)會(huì)考慮這一點(diǎn),而且也會(huì)說(shuō)服標(biāo)準(zhǔn)主體接納這個(gè)建議。
分歧:服務(wù)器中立到什么程度
Batman和Meteor明顯依賴(lài)服務(wù)器:Batman是為Rails設(shè)計(jì)的,而Meteor本身就是服務(wù)器。其他大多數(shù)都追求服務(wù)器中立。但實(shí)際上,Ember的架構(gòu)、強(qiáng)制性規(guī)定,以及某些工具都傾向于Rails開(kāi)發(fā)者。當(dāng)然,Ember絕對(duì)也能跟其他服務(wù)器技術(shù)搭配,只不過(guò)眼下還需要較多手工配置。
技術(shù)門(mén)派概覽
以下是所有JavaScript庫(kù)/框架的基本技術(shù)細(xì)節(jié)。
Backbone
- Who: Jeremy Ashkenas和DocumentCloud。
- What:
+ 用JavaScript實(shí)現(xiàn)模型-視圖,MIT許可。
+ 只有一個(gè)文件,1000行代碼,在所有庫(kù)中最?。?br /> + 功能極其專(zhuān)一,只提供REST可持久模型及簡(jiǎn)單路由和回調(diào)(以便你知道何時(shí)渲染視圖,但視圖渲染機(jī)制由你自己選擇)。
+ 名氣最大,很多大牌站點(diǎn)都在用(也許是因?yàn)樗钚?,容易部署)?/li> - Why:
+ 非常小,使用它之前,你完全可以通讀并理解它的源代碼。
+ 不會(huì)影響你的服務(wù)器架構(gòu)或文件組織方式。可以在頁(yè)面的某一部分內(nèi)運(yùn)行——不需要控制整個(gè)頁(yè)面。
+ Jeremy好像進(jìn)入了一種禪宗所謂的入定的狀態(tài),對(duì)一切都能坦然接受。他就像一個(gè)大人,看著一群孩子在那里辯論。 - Where: GitHub 及 自有站點(diǎn)。
- When: 至今已誕生近兩年了。
Meteor
- Who: Meteor 開(kāi)發(fā)團(tuán)隊(duì)(他們剛募集到1120萬(wàn)美元投資,因此可以全職開(kāi)發(fā))。
- What:
+ 前瞻性極強(qiáng)的一個(gè)框架,想不出有誰(shuí)那么激進(jìn)過(guò)(也許Derby算一個(gè))。
+ 將一個(gè)服務(wù)器端運(yùn)行時(shí)環(huán)境(用Node+Mongo搭建)和一個(gè)客戶(hù)端運(yùn)行時(shí)環(huán)境銜接起來(lái),讓你的代碼在兩端都能運(yùn)行,還包含數(shù)據(jù)庫(kù)。利用WebSockets實(shí)現(xiàn)所有客戶(hù)端和服務(wù)器之間的同步。
+ 在修改代碼時(shí)就“實(shí)時(shí)部署”——客戶(hù)端運(yùn)行時(shí)可以即時(shí)更新而不丟失狀態(tài)。
+ 可以看看這個(gè)視頻,對(duì)它的認(rèn)識(shí)就會(huì)更全面。
+ 跟會(huì)上與我有過(guò)交流的所有人一樣,我也衷心希望這個(gè)框架獲得成功——Web開(kāi)發(fā)就需要這種激進(jìn)的改革才能真正進(jìn)步。 - Why: 你實(shí)在覺(jué)得做常規(guī)Web開(kāi)發(fā)太無(wú)聊了,想找點(diǎn)刺激。
- Where: GitHub 和 自有站點(diǎn)。
- When: 誕生時(shí)間不長(zhǎng);除了其核心團(tuán)隊(duì)在用,不知道還有沒(méi)有其他站點(diǎn)實(shí)際在用Meteor。不過(guò),這個(gè)團(tuán)隊(duì)真是在嚴(yán)肅地做著一件前無(wú)古人的事。
Ember
- Who: Yehuda Katz (之前開(kāi)發(fā)過(guò)jQuery和Rails)、Ember團(tuán)隊(duì)和Yehuda的公司Tilde。
- What:
+ 構(gòu)建“超級(jí)Web應(yīng)用”所需的一切,MIT許可。
+ 功能最多,體積最大。
+ 融入了很多設(shè)計(jì)理念,涉及如何分解并對(duì)頁(yè)面進(jìn)行層次控制,以及如何利用一個(gè)狀態(tài)機(jī)驅(qū)動(dòng)的系統(tǒng)聯(lián)結(jié)各個(gè)層次。
+ 正在開(kāi)發(fā)一個(gè)功能非常完善的數(shù)據(jù)訪(fǎng)問(wèn)庫(kù)(Ember.Data)。
+ 要在運(yùn)行時(shí)控制整個(gè)頁(yè)面,因此不適合開(kāi)發(fā)大頁(yè)面上的“富應(yīng)用區(qū)”。
+ 對(duì)文件、URL等都有相當(dāng)嚴(yán)格的一套約束,不過(guò)要是不喜歡,你可以重寫(xiě),只要你知道怎么做就OK。
+ 設(shè)計(jì)靈感來(lái)自Rails和Cocoa。
+ 工具:為Rails提供項(xiàng)目模板(但如果你手工編寫(xiě)代碼,也可以使用其他服務(wù)器端平臺(tái))。 - Why: 常見(jiàn)的問(wèn)題應(yīng)該有通用的解決方案——Ember提供了所有通用解決方案。
- Where: GitHub 和 自有站點(diǎn)。
- When: 尚未發(fā)布1.0版,但也快了。然后,API基本就能穩(wěn)定下來(lái)。
AngularJS
- Who: Google(他們內(nèi)部在使用)。
- What:
+ 用JavaScript實(shí)現(xiàn)模型-視圖-其他,MIT許可。
+ 基于DOM的模板,具備可觀察能力、聲明綁定機(jī)制,還有準(zhǔn)MVVM式的代碼風(fēng)格(他們自己說(shuō)是Model-View-Whatever)
+ 內(nèi)置基本URL路由和數(shù)據(jù)持久化能力
+ 工具:附帶一個(gè)Chrome調(diào)試器插件,讓你在調(diào)試的時(shí)候能夠查看模型;還附帶一個(gè)Jasmine測(cè)試框架。 - Why:
+ 從概念上講,他們說(shuō)這個(gè)框架相當(dāng)于一個(gè)“填料層”,蓋在當(dāng)前瀏覽器上,以實(shí)現(xiàn)未來(lái)的瀏覽器將可能原生具備的能力(即聲明綁定和可觀察能力)。因此,我們現(xiàn)在就應(yīng)該著手這么來(lái)寫(xiě)代碼了。
+ 對(duì)服務(wù)器架構(gòu)或文件組織方式?jīng)]有影響??梢杂迷陧?yè)面的某一小部分中——不需要控制整個(gè)頁(yè)面。 - Where: GitHub 和 自有站點(diǎn)。
- When: 成品級(jí)框架,Google已經(jīng)搞出來(lái)有一段時(shí)間了。
Knockout
- Who: Knockout 團(tuán)隊(duì)和社區(qū)(核心團(tuán)隊(duì)目前有三個(gè)人,包括我)。
- What:
+ 用JavaScript實(shí)現(xiàn)模型-視圖-視圖模型(MVVM,Model-View-ViewModel),MIT許可。
+ 功能集中在富用戶(hù)界面元素:基于DOM的聲明綁定模板,可觀察的模型加自動(dòng)依賴(lài)檢測(cè)。
+ 沒(méi)有限定URL路由或數(shù)據(jù)訪(fǎng)問(wèn)——可組合任意第三方庫(kù)(例如,用Sammy.js做路由,用純Ajax實(shí)現(xiàn)存儲(chǔ))。
+ 在降低使用門(mén)檻方面下了很大工夫,提供詳盡的文檔和交互式示例。 - Why:
+ 只做好一件事(UI),向后兼容到IE6。
+ 對(duì)服務(wù)器架構(gòu)或文件組織方式?jīng)]有影響??梢杂迷陧?yè)面的某一小部分中——不需要控制整個(gè)頁(yè)面。 - Where: GitHub 和 自有站點(diǎn)。
- When: 到現(xiàn)在已經(jīng)正式發(fā)布近兩年了。
Spine
- Who: Alex MacCaw。
- What:
+ 用JavaScript實(shí)現(xiàn)MVC,MIT許可證。
+ 由最早為O'Reilly一本書(shū)寫(xiě)的示例代碼發(fā)展而來(lái),已成為一個(gè)OSS(Open Source Software,開(kāi)源軟件)項(xiàng)目。
+ 是Backbone的一個(gè)衍生版(看名字就知道3)。 - Why: 你喜歡Backbone,但又想要點(diǎn)不一樣的東西。
- Where: GitHub 和 自有站點(diǎn)
- When: v1.0.0已經(jīng)發(fā)布。
Backbone和Spine都是“脊椎”的意思。——譯者注
Batman
- Who: Shopify (一家電子商務(wù)平臺(tái)公司)的團(tuán)隊(duì)。
- What:
+ 在JavaScript中實(shí)現(xiàn)MVC,幾乎是專(zhuān)門(mén)為Rails+CoffeeScript開(kāi)發(fā)者定制的,MIT許可。
+ 是所有框架中強(qiáng)制性規(guī)定最多的。你必須遵守其約定(例如,怎么組織文件和URL)。否則,就像他們幻燈片中說(shuō)的,“你還是用其他框架吧”。
+ 非常完善的框架,具有相當(dāng)豐富的模型、視圖和控制器,還有路由。當(dāng)然,還有可觀察機(jī)制。
+ 基于DOM的模板。 - Why: 如果你使用Rails和CoffeeScript,你找到親人了。
- Where: GitHub 和 自有站點(diǎn)。
- When: 當(dāng)前版本 0.9,幾個(gè)月內(nèi)將發(fā)布1.0版。
CanJS
- Who: Bitovi(一家JavaScript咨詢(xún)/培訓(xùn)公司)的團(tuán)隊(duì)。
- What:
+ 用JavaScript實(shí)現(xiàn)MVC,MIT許可。
+ REST可持久模型、基本的路由、基于字符串的模板。
+ 知名度不高(我也是上周才聽(tīng)說(shuō)它的),但它的前身卻是原來(lái)的JavaScriptMVC項(xiàng)目。 - Why: 旨在集上述各技術(shù)門(mén)派之所長(zhǎng),提供與它們類(lèi)似的功能,同時(shí)又保持體積小巧。
- Where: GitHub 和 自有站點(diǎn)。
- When: 1.0 版已經(jīng)發(fā)布了。
總結(jié)
如果你正在考慮選型的問(wèn)題,想知道上面這些框架/庫(kù)中的哪一個(gè)最適合你的新項(xiàng)目,那我建議你重點(diǎn)關(guān)注以下兩點(diǎn)。
- 功能范圍。你想讓這個(gè)框架或庫(kù)為你做多少事兒?你的項(xiàng)目是從頭做起,因而需要一個(gè)能貫穿始終的完整的各項(xiàng)功能齊備的架構(gòu)嗎?或者,你其實(shí)更喜歡自己來(lái)挑選模式和庫(kù)?對(duì)不同的項(xiàng)目,不同的團(tuán)隊(duì),任何選擇都有價(jià)值,都是正確的。
- 設(shè)計(jì)美學(xué)。你看過(guò)它們的代碼嗎,用沒(méi)用過(guò)自己選擇的框架構(gòu)建出了一些小巧的應(yīng)用?你喜歡這樣做嗎?不要只看它們的說(shuō)明或者功能列表就作出選擇:那些信息有價(jià)值,但不全面。打個(gè)比方,如果你置自己主觀的編碼經(jīng)驗(yàn)于不顧,那就像在選擇小說(shuō)時(shí)只看它有幾章幾節(jié),或者在找對(duì)象時(shí)只看其簡(jiǎn)歷或個(gè)人描述。
盡管存在分歧,但我認(rèn)為所有技術(shù)門(mén)派有一個(gè)重大的共性:它們都踐行了模型與視圖分離的思想。而這個(gè)思想早在Web誕生之前就已存在,到現(xiàn)在差不多有20年歷史了。這么說(shuō)吧,就算你只做一個(gè)基本的Web應(yīng)用的UI,在客戶(hù)端應(yīng)用這一思想也永遠(yuǎn)是正確的。