2012年7月30日

比較Backbone.js, Angular.js, Ember.js, Knockout.js 心得

還記得第一次寫網站的時候,我無意間寫成了 SPA(single page application),當時還沒有SPA這個詞,後來因為廣告主需要不同 url location 頁面的廣告展示,只好把部分網站改成一般網頁。但是一直以來我對於提高整體溝通效率以及使用端的回應效率抱持相同的想法,希望能夠把更多回應放到 client 處理,讓server 做好 api 提供者的角色,可以讓網站回應更即時而親切,這篇心得文不會詳細走訪每個技術層面,而是提供概括的入門使用情況。

現在client-side javascript MV*(MVVM, MVC等) framework實作產量豐富,Backbone.js, Spine.js, Angular.js, Ember,js, Knockout.js, Batman.js, Javascript MVC, SproutCore.js, Cappuccino.js 好像每個高手都要發明一套才行,不過其實各框架的目的不盡相同,其中我比較感興趣的是Backbone.jsKnockout.js 還有強大的Angular.jsEmber.js,大家在玩的時候可以比較一下他們的todo list是怎麼做的,todo list範例已經是新框架誕生時要遵守的"行規"了。



Backbone.js

Backbone.js大家絕對都聽過,有廣大的社群支持者,文件和教學很完整,使用他第一次讓我可以把javascript event整理成清楚好維護的方式。雖然我比較常獨立栽種程式碼,但是我相信一個網頁前端團隊合作用Backbone.js會是很輕鬆的,module的切割加上他幾乎沒有改變html原有的寫作方式,不會嚇跑負責html和css的夥伴或任何人,可以有乾淨的工作區分。

Backbone.js在功能上可以說是提供了比較...基礎的功能協助,其實可以說什麼都沒做吧...,相較於在使用其他框架時,會面臨需要思考如何把強大的功能"降級",這很痛苦,Backbone.js讓我可以build from scratch,這往往更容易完成我想要的功能也更容易除錯,也很容易改造一些原始運作,但是我有時候發現程式碼變得非常龐大,而且事必躬親,事情似乎被複雜化了,我常想這是必要的代價嗎?  使用到後來發現我愛的其實是Underscore.js吧,Underscore.js程式碼的品質很好。

其他Backbone.js相對比較好的地方像是collection的概念,還有整個框架檔案很小,缺點(特點)就是沒有data-binding,有人試圖幫他做了一個,最後效能太差收掉了。

補充一下基於Backbone.js的兩個成熟框架,MarionettejsChaplin。由於Backbone幾乎只滿足了前端框架的最基本需求,這兩個框架則解決實際的使用上的問題,像是清除event-listener(lifecycle),還有更好的應用架構支援和Controller,而不是只有單純的Router獨挑大梁,以及有更完整的View繼承和預設render方式,和整合AMD支援等等。



Angular.js

Angular.js和Ember.js讓我第一次發現原來View和Model可以做binding,而且是透過非常簡單的方式,簡直美好,雖然Knockout.js也有data binding,但是就是沒有Angular.js用起來直覺。

Angular.js提供的template樣版也是在我用過的javascript MV*當中最喜歡的,用起來有點像是Jinja2的感覺。

Angular.js還提供簡單的方式讓你自己做directive,可以想像在UI當中加入一個小東西就能完成常用的功能。

Angular.js的routing也非常簡單易懂,但是太過簡單以至於只能用作者希望的方式來用,加上他本身用singleton模式,只能有一個app instance,讓我無法在一個route中同時作出複雜的動作,或是更新多個View,目前無法符合我的需求(更新:後來我透過directives完成了,directives是一個能夠讓你做出類似網頁widget的強大功能),不過作者說不適合在1.0時釋出太複雜的東西,所以我們就持續關注吧。

令人驚訝的是,Angular.js自帶一組強大的end to end testing工具,而且非常的簡單好懂。

另外Angular.js和Ember,js, Knockout.js同樣潛在的缺點(特點)是,有些人可能不希望程式的邏輯跑進html中,但是我認為簡單繁瑣的邏輯應該允許放在最合適的地方,進一步了解可以看一下Angular.js作者在Quora上的見解,這點就見仁見智。

整體而言我對Angular.js的未來非常看好,現在在Google的CDN上也可以取得了,可見Google對他的重視,預計九月初會釋出1.2版。


Ember.js

一樣是後起之秀,Ember.js是從SproutCore.js出來又從Amber.js改頭換面成了Ember.js。這是和我初始想法最接近的Javascript client-side framework,寫起來很有感覺,有時候寫程式真的不需要選什麼大家都在用還是評價最高的東西,選一個和自己頭腦思考方式最接近的就是最好的,這點也是因人而異的。

Ember.js的Model是我最喜歡的方式,Backbone.js相對顯得囉嗦和貧乏,Model中的computed property可以選擇連動的屬性,one-way or two-way binding可以自由搭配,他使用的Handlebars.js template比Underscore.js和Mustache.js提供的都要更好用,我建議Backbone.js使用者也可以看看Handlebars.js,他在功能和簡單兩邊取得了平衡,算是非常不錯的javascript template引擎。

雖然我舉雙手贊成以後template盡量都移到client-side來做,但是我必須說,現在所有的client-side template功能和server-side經年累月琢磨出來的template都還比不上,其實Model和Controller也是,還有很多可以加強的功能,因為還要考慮client裝置的能力和網路環境的限制,不能像server端的東西包山包海。至少現在Angular.js和Ember.js看起來是站在巨人的肩膀上。Ember.js在attribute binding功能上更勝一籌,Angular.js目前的1.0版則較為簡單易用。

Ember.js還有一個非常特別的地方是Finite State Machine Routing,他原本一直沒有提供routing功能,後來才透過他的State實做了routing,目前官網還沒有很好的文件。和其他框架都不同的是,他的routing是可以和location脫鉤的finite state machine,但是如果你希望,他也可以在改變state時自動幫你更新location,非常強大,我只能說Ember.js野心太大,希望不要搞砸,可以看一下原本幫Ember.js寫RouteManager外掛的作者的這篇來了解中間的不同,State Machine的設計概念我是支持的,軟體流程可以做的比較清楚,但是目前整體routing語法太冗長、贅字太多這點有待改進,View裡面的outlet的局限性也是我用起來覺得不順手的地方,算是個缺點吧。

另外Ember.js最大的缺點就是文件不齊全或沒跟上最新版,學習時間比其他框架要長一點。



Knockout.js

Knockout.js 很久以前就被facebook推薦做為mobile web前端的框架,我覺得Knockout.js算是比較成熟的MVVM框架,他不試著包山包海,他迷人之處就是他專心做好data-binding,然後在這之上搞好template,因為他很專一和成熟所以他有很多細心的地方,像是你可以在data-binding的過程中很容易的界接jquery的aniamtion,很多其他框架就只是幫你即時做binding而,還有如何從jquery中調用Knockout.js的value和context, Knockout.js 給使用者很大的自由,甚至他還想到怎樣做可以更方便的把UI上資料同步遠在server的資料庫(for Rails),另外在template上也有許多巧思可以體會到他設想周到。

Knockout.js的缺點就是我不喜歡他的語法,雖然自己進去改一些東西可能也能解決,但這會讓我覺得我和作者的靈魂不夠接近,這是很嚴重的問題,而且他太成熟了,不是一個追逐最新潮流的碼農可以拿出來炫耀的工具,這也是很嚴重的問題,哈。

由於Knockout.js 沒有routing功能(有routing功能的框架通常官網也會直接展示),我們可以使用Crossroads.js, Director.js或是Sammy.js,三個都很不錯,Director.js是Server和Client兼具,Sammy.js是我一直在關注的工具,他一樣專注在一件事情上,我很喜歡他的語法,用起來有jquery和server-side routing結合的感覺,不像很多框架在語法上都喜歡自成一格,模仿jQuery語法相當明智,而且現在也有html5 history support了,可以和Knockout.js結合的很好。

另外還有個有趣的東西叫做Knockback.js,他是Backbone.js和Knockout.js產下的混血兒, Knockback.js 把Backbone.js的ORM, routing, serialization和Knockout.js的MVVM data-binding各取所長的結合在一起,我是不敢用基因改良的東西啦,我怕會有基因突變,期待有人分享心得了。



延伸閱讀:

如果不怕英文的人我建議看Javascript Web Application
另外所有寫Javascript的人我都強烈建議要讀Javascript 設計模式