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