你很喜歡Gmail和Trello之類的單頁面應(yīng)用,但是不太確定該從何開始。也許你的JavaScript代碼是如此的雜亂無章,以致于你很想在下一個項目上嘗試下JavaScript MVC庫和框架,卻苦于沒有頭緒?我正在撰寫一本單頁面應(yīng)用的書,所以我閱讀了大量網(wǎng)上的相關(guān)資料。在這里我嘗試提供一些看法,希望可以幫助你下決定。 簡介這里討論的是時下最熱的框架,AngularJS、Backbone、Ember和Knockout。同時提到了Batman、CANjs、Meteor和Spine,但是沒有詳細(xì)展開。 我們從多個不同的角度考察每個項目,包括社區(qū)、領(lǐng)導(dǎo)、成熟度、大小、依賴、互操作性、啟發(fā)、理念和特性。 社區(qū)社區(qū)是一個衡量任何開源項目健康程度的重要指數(shù)。以下表格顯示了GitHub上每個項目的關(guān)注者數(shù)量。 你當(dāng)然不該僅僅根據(jù)這些數(shù)據(jù)做決定,但是它們確實為你提供了關(guān)于這些框架的一些感性認(rèn)識: 最主流:
正在高速成長的:
關(guān)注總量較低但是增長迅猛的:
增長性特別值得注意的是AngularJS 13個月以來的驚人增長(379%)。在你做決定的時候要考慮上這一點。下面的圖表比較了13個月以來GitHub關(guān)注者的增長速度,可以看出某個項目的社區(qū)成長的速度??紤]到原先的社區(qū)大小,Meteor(130%)、Ember(104%)、Knockout(76%)和Backbone(64%)的增長速度也很驚人。 領(lǐng)導(dǎo)了解項目的核心開發(fā)者的背景,他們創(chuàng)建框架時嘗試解決的問題,有助于你欣賞他們在設(shè)計上的決策和動機(jī)。例如,David Heinemeier Hansson,流行的Ruby on Rails框架的締造者,是37signals的簽約開發(fā)者,從事項目設(shè)計,每周只有10小時能花在開發(fā)框架上。Ruby on Rails事實上是從他和37signals的簽約工作中提取出來的。這一背景有助于你理解為什么這個框架需要將開發(fā)效率提升到極限——這意味這使用大量的約定(已經(jīng)做出的決定)和支架程序(生成的代碼)。下面,我將介紹JavaScript MVC 框架的締造者,也許也能激起你對他們的工作的欣賞。 BackboneJeremy Ashkenas和DocumentCloud Jeremy Ashkenas是CoffeeScript編程語言、Backbone.js JavaScript框架和Underscore.js JavaScript工具庫的創(chuàng)立者。根據(jù)維基百科,他現(xiàn)在在NYTimes/DocumentCloud從事互動新聞方面的開發(fā)。 圖片來自The Canadian University Software Engineering Conference。 AngularJSAngularJS最初由Google的Mi?ko Hevery和Adam Abrons于2009年開發(fā),當(dāng)時是一個在線JSON存儲服務(wù)的一部分。Abrons后來離開了這個項目,但是在Google工作的Hevery繼續(xù)開發(fā),和Google的員工Igor Minár、Vojta Jína一起維護(hù)這個庫。 圖片來自Devoxx 2012 KnockoutSteve Sanderson是Knockout的原作者。Steve Sanderson現(xiàn)在為微軟工作,他所在的團(tuán)隊開發(fā)ASP.NET、IIS和其他web項目。他以前以外包開發(fā)者或顧問身份為Bristol周邊的客戶開發(fā).NET下的軟件,他還為Apress寫了一些書,包括《Pro ASP.NET MVC框架》。 EmberEmber核心成員中最知名的公眾人物是Yehuda Katz和Tom Dale。 Yehuda Katz是Ember.js、Ruby on Rails和jQuery的核心開發(fā)者,他白天的時間花在他創(chuàng)辦的創(chuàng)業(yè)公司,Tilde Inc.。Yehuda是暢銷書《jQuery in Action》和《Rails 3 in Action》的作者之一。 Tom Dale原先在SproutCore團(tuán)隊工作。他以前是蘋果軟件工程師,在開發(fā)MobileMe和iCloud應(yīng)用時精通了前端JavaScript技能。
圖片來自Ember Team MeteorMeteor的開發(fā)團(tuán)隊剛剛得到了1.12千萬美金,所以他們可以全職開發(fā)。他們的團(tuán)隊有12名開發(fā)者,每個開發(fā)者的簡歷都讓人印象深刻。這個團(tuán)隊擁有雄心勃勃的計劃,超越了大多數(shù)專注于組織客戶端代碼和狀態(tài)的JavaScript MVC框架。Meteor是一個全端框架,包括服務(wù)器架構(gòu)和數(shù)據(jù)庫。 成熟度評估框架的成熟度可以幫助你理解在項目中使用新技術(shù)的風(fēng)險。未經(jīng)考驗的新框架在文檔、擴(kuò)展性、穩(wěn)定性(API改變)和支持(尋找了解該框架的開發(fā)者來維護(hù)代碼)方面可能存在問題,這些問題可能導(dǎo)致出乎意料的結(jié)果,即使從其他方面看起來決策很明智。需要考慮的項目包括:多少生產(chǎn)環(huán)境下的應(yīng)用使用這些框架?這些應(yīng)用有多少用戶?文檔是否良好?例子和教程是否充足?例子是否過時?API是否穩(wěn)定?其他開發(fā)者了解或正打算了解這門技術(shù)么?
大小了解每個框架的大小,它會在你的應(yīng)用中增加多少分量是很重要的。大小會影響性能,不過它同時也會暗示你這個框架的雄心有多大,你學(xué)習(xí)它可能需要花多少時間,以及它提供多少幫助你構(gòu)建應(yīng)用的方式(即特性和魯棒性)。一個框架的野心越大,特性越多,通常也就意味更難在應(yīng)用的頁面上將它與其他部件組合。輕量的框架更像一個庫,將他集成到你的項目中所耗費的精力也相對較小。 包括Backbone和Spine在內(nèi)的一些項目為自己的輕量而自豪,這些項目更多地將自己視作庫,而不是框架。通常這些小型的框架留下了空間,你可以使用你自己的庫來實現(xiàn)特定功能,例如模板和路由。我在討論這些框架的特性的時候?qū)⒗^續(xù)討論這個話題。 包括Ember和AngularJS在內(nèi)的其他項目雄心勃勃,更適合叫做框架。它們通常擁有更多內(nèi)建的特性,更少依賴外部庫。 下面的列表顯示了我更傾向于將哪些項目歸入庫或框架:
依賴性使用這些項目構(gòu)建真實世界的應(yīng)用的時候還需要哪些庫?以下的圖表展示了為了保證開發(fā)效率每個庫所需的依賴,以及這些依賴的大小。 通過從cdnjs下載庫,我們收集了這些數(shù)據(jù)。在實踐中,大多數(shù)的項目會使用jQuery配合這些框架處理DOM,因為需要動畫和AJAX。在移動應(yīng)用中,使用Zepto.js來代替jQuery處理DOM不是什么稀奇的事。Zepto.js是一個比jQuery輕量得多的庫。雖然Zepto.js不支持Internet Explorer,但是移動應(yīng)用通常不需要為此操心。AngularJS包含了一個jQuery 的縮減版jQLite。但是如果你在項目中使用了jQuery的話,它會被覆蓋。AngularJS團(tuán)隊鼓勵開發(fā)者,如非必要,不要添加完整的jQuery庫。為了幫助你做出正確的選擇,下面的表格同時顯示了移動版(假定使用Zepto.js)和web版(假定使用jQuery)。 互操作性這一部分討論是否框架設(shè)計為控制整個頁面或者它可以被用于現(xiàn)存頁面的一個部分——你可能想漸漸將新技術(shù)引入現(xiàn)有的項目。前面的庫和框架的討論基本可以體現(xiàn)每個項目的互操作性,庫更傾向于很容易地集成到現(xiàn)存的項目,而框架為你做更多的事,但是不容易和其他項目配合。 AngularJSAngularJS可以和其他庫很好地配合,但是它鼓勵開發(fā)者們考慮是否可以不用jQuery和jQueryUI.事實上Angular內(nèi)置了一個jQuery的子集jqLite。遵循這一實踐的理由是讓單元測試更容易,因為很多依賴庫和插件設(shè)計的時候沒有考慮單元測試,相應(yīng)地更難和單元測試配合。在實踐中,大多數(shù)的開發(fā)者最終還是因為某些特性使用了jQuery. Backbone由于Backbone的小尺寸和無預(yù)設(shè)的架構(gòu),將其包含在眾多流行的客戶端庫和服務(wù)器端技術(shù)中很容易。 Ember.js被設(shè)計為在運(yùn)行時控制整個頁面,所以不太適合用于頁面的部分。 Knockout.js可以在項目中作為小組件使用,不控制整個頁面。 啟發(fā)記者采訪音樂家時最愛問的問題是“你在成長的時候聽哪些藝術(shù)家的音樂,或者說,誰啟發(fā)了你?”這個問題常常使得讀者能夠預(yù)期音樂家的聲樂。這些框架中大部分的觀念都不是全新的,而是來自于創(chuàng)造者以前工作的項目中喜歡的部分。這一部分總結(jié)了我從框架創(chuàng)造者的訪談中收集到的關(guān)于啟發(fā)的信息。 AngularJSHTML類的聲明性的語言,Adobe和Flex、微軟的WPF\Silverligt等RIA技術(shù)給AngularJS的影響很深。這些聲明性技術(shù)沒有”主體“方法,僅僅表達(dá)需要發(fā)生什么,而不指定具體實現(xiàn)。視圖和模型中的數(shù)據(jù)雙向綁定是這一聲明式編程風(fēng)格在絕佳例子。此外,在Google的服務(wù)器端Java代碼中大量使用的依賴注入和IOC容器(特別是Juice)也啟發(fā)了AngularJS的創(chuàng)造者。他們重視單元測試,需要框架被設(shè)計允許依賴注入,這樣測試就可以從其他應(yīng)用層剝離出來,運(yùn)行起來也會更快。 EmberTom Dale在Quora上談了Ember受到的影響:
此外,Ember.js是SproutCore JavaScript庫的進(jìn)化版,SproutCore停止仿效Cocoa而更多地借鑒jQuery的時候,Ember誕生了,理解這一點很重要。 Knockouthanselminutes的播客提供了Steve Sanderson受到哪些方面啟發(fā)的背景信息??偨Y(jié)一下,MVVM設(shè)計模式和微軟的WPF、Sliverlight等聲明性技術(shù)是最大的啟發(fā)者。你可能會發(fā)現(xiàn)Knockout的最佳特性——聲明性的數(shù)據(jù)雙向綁定——和Anjular相似,因為兩者的啟發(fā)者是相似的。 理念報紙在報道新聞的時候努力保持中立。唯一的例外是編者案,鼓勵表達(dá)觀點,作者通常在問題上占據(jù)一個強(qiáng)烈的立場。但是大多數(shù)情況,這兩者既不是嚴(yán)格的中立報道,也不是強(qiáng)烈的意見表達(dá),而是位于兩者之間的連續(xù)統(tǒng)。技術(shù)框架也有類似的劃分,即是否強(qiáng)主張。例如,Ruby on Rails推崇約定優(yōu)于配置,并且為開發(fā)者做了大量決定,包括文件結(jié)構(gòu)和數(shù)據(jù)訪問。相應(yīng)地,它被認(rèn)為是強(qiáng)主張的。其他Sinatra類的服務(wù)器端框架更輕量,并不預(yù)設(shè)文件結(jié)構(gòu)和數(shù)據(jù)訪問。相應(yīng)的,被看成是無主張的。服務(wù)端框架有理念,客戶端JavaScript MVC框架同樣有,我們討論的框架也可以被置于強(qiáng)主張和無主張的連續(xù)統(tǒng)中考察。讓我們看看每個項目,然后討論他們的理念。 Backbone: 無主張Backbone是最開明的框架,極度無主張,允許開發(fā)者做出自己的決定,有時這會導(dǎo)致代碼差異過大而難以維護(hù)。唯一的例外是Backbone假定服務(wù)器端有一個REST服務(wù),我會在特性部分詳細(xì)討論這一點。這一假定可以通過覆蓋模型的sync方法來繞過。 AngularJS: 強(qiáng)主張AngularJS有較強(qiáng)的主張,特別是它強(qiáng)調(diào)可測試性和依賴注入。此外,HTML類的聲明性編程很棒的理念也在框架中廣泛體現(xiàn)。 Ember: 極度強(qiáng)主張Ember力求開發(fā)者僅對應(yīng)用的特有部分作決定,其余全部交給約定和支架。這個理念和Ruby on Rails和jQuery很接近。這一理念最好的表達(dá)出現(xiàn)在的網(wǎng)站上:
Ember標(biāo)準(zhǔn)化了文件和url結(jié)構(gòu),當(dāng)然,有必要的時候也允許你覆蓋這些設(shè)定。你可以預(yù)期的是大量的代碼會為你生成,大量的類似文件結(jié)構(gòu)的約定。相應(yīng)地,你需要做出的常規(guī)選擇更少,因為框架已經(jīng)為你選定了合理的默認(rèn)值,你可以著手構(gòu)建你的應(yīng)用的特殊部分。 Knockout: 無主張路由和數(shù)據(jù)存儲留給開發(fā)者決定。不預(yù)設(shè)文件或URL結(jié)構(gòu)。甚至允許用基于字符串的模板替換聲明性的基于DOM的模板。 特性我們可以將這些JavaScript MVC框架看成是幫助開發(fā)者構(gòu)建單頁應(yīng)用的常用特性集合。每個框架實現(xiàn)這些特性的方式,或者不實現(xiàn)這些特性的方式(通過其他庫來補(bǔ)全框架的功能)是值得留心的。 JavaScript MVC框架的主要特性是什么?
除此以外,一些框架提供常用的語言層面的服務(wù),例如通用的pub/sub事件模型和面向?qū)ο蟮睦^承支持。 數(shù)據(jù)綁定這是最受吹捧的特性。你通過HTML input修改了數(shù)據(jù),綁定到input的JavaScript對象馬上更新,其他綁定的用戶接口元素也隨之更新。在很多框架中,反之亦然。如果你修改了JavaScript對象,html會自動刷新。這是一個web上的雙向的數(shù)據(jù)綁定,我們在Flex、Windows Forms、WPF等富客戶端應(yīng)用框架中見過這類綁定。以下的表格顯示了哪些框架支持?jǐn)?shù)據(jù)綁定。 有些人可能持有異議,因為Backbone和Spine部分支持?jǐn)?shù)據(jù)綁定。但是我覺得大量工作需要留給開發(fā)者,保險起見,不如說這些庫不支持這些特性。 視圖模板客戶端的JavaScript數(shù)據(jù)模型需要穿插在HTML中,這些框架采用兩種方式解決問題。 基于字符串的模板(目前最流行的是handlebars.js),將字符串、文本模板中的動態(tài)部分替換為模型中的數(shù)據(jù)。字符串常被提到也飽受爭議的特性之一是性能。其缺點是調(diào)試控制語句類的邏輯很困難。 基于DOM的模板擁抱標(biāo)記語言的聲明式本性,這是開了掛的html,通過html中的附加屬性來描述需要的綁定和事件。這些庫需要的代碼大大減少,為開發(fā)者做了很多事情。 模型(可觀察的:跟蹤改動)一些框架(Backbone、Spine)更專注于模型,要求開發(fā)者在base模型的基礎(chǔ)上擴(kuò)展JavaScript類,通過 其他庫(AngularJS)對頁面上的所有綁定的DOM元素作臟檢查,因為沒有標(biāo)準(zhǔn)的get和set訪問器。因此將這些庫用于大頁面時將導(dǎo)致性能問題。這些庫不僅需要更少的刷新模板的代碼,也不需要你使用特定的get和set訪問器來修改模型中的數(shù)據(jù),所以你可以使用原始的JavaScript對象。這大大提升了開發(fā)效率,這一點在框架的初學(xué)者身上體現(xiàn)得尤為明顯。 數(shù)據(jù)存儲這些框架通過以下方式將數(shù)據(jù)存儲到服務(wù)器
REST一些框架默認(rèn)預(yù)設(shè)后端有非常整潔的REST JSON服務(wù),并且,至少在默認(rèn)的情況下,前端與后端頻繁交互,在后臺異步更新數(shù)據(jù),而用戶界面響應(yīng)流暢。這些框架內(nèi)部使用jQuery或Zepto發(fā)送合適的AJAX請求給服務(wù)器。用戶界面的HTML DOM元素監(jiān)聽?wèi)?yīng)用的JavaScript對象模型的改動,同步機(jī)制得到模型屬性的更改提醒,將改動發(fā)送給REST服務(wù),確保模型和服務(wù)器同步。 在線和離線Backbone默認(rèn)在客戶端保存數(shù)據(jù)之前發(fā)送請求,這樣服務(wù)器端和客戶端同步就很容易。和Backbone非常類似的Spine框架,采用了不同的方式,在異步發(fā)送請求到服務(wù)器前,先在客戶端存儲記錄,這提供了更好的用戶界面響應(yīng),在移動應(yīng)用中常發(fā)生的離線狀態(tài)下也能工作。如果你的項目需要支持離線,需要了解清楚框架對該特性的支持 DIY這些框架要求開發(fā)者使用 數(shù)據(jù)存儲特性Meteor之類精心制作的框架擁有更完整的數(shù)據(jù)存儲方案,但是要求服務(wù)器端有MongoDB數(shù)據(jù)庫。這類方案試圖提供一個擴(kuò)展性優(yōu)異的默認(rèn)解決方案,提供從頭到尾的JavaScript開發(fā)體驗。 以下的表格總結(jié)了每個框架是如何處理數(shù)據(jù)存儲的。 路由將URL路由映射到JavaScript函數(shù),可以支持瀏覽器的后退按鈕。單頁應(yīng)用最大的缺點之一是由于頁面無刷新,瀏覽器歷史不會添加條目,所以后退按鈕通常無法將用戶帶回頁面的前一狀態(tài),除非開發(fā)者在主要的狀態(tài)改變時做一些額外的工作,通過在URL后附加井號,或者,使用現(xiàn)代瀏覽器的push和pop狀態(tài),實現(xiàn)狀態(tài)跟蹤機(jī)制??傊?,大多數(shù)項目都提供基本、初步而有用的功能。Knockout的做法很簡單,允許你使用其他的第三方開源庫。 蘋果對蘋果考察各個框架的特性之后,我發(fā)現(xiàn)我并不是在做一個“蘋果對蘋果”的比較。一個更為公平的比較也許是將AngularJS和EmberJS之類全面的框架與配合第三方庫使用的Backbone和KnockoutJS之類的MV*框架進(jìn)行比較。具體來說,下面的比較會更有意義:
以后的博客中我會繼續(xù)深入。 告訴我更多為項目選擇JavaScript MVC框架時有大量需要考慮的事項,我希望本文是一個良好的開始。請在評論中分享你使用這些框架的體驗,包括它們的優(yōu)異之處,也包括它們使用上的陷阱。 |
|