引言
最近在Angular社群的原型開發者間,一種全Javascript的開發架構MEAN正突然流行起來。其首字母分別代表的是:(M)ongoDB——NoSQL的文件資料庫,使用JSON風格來儲存資料,甚至也是使用JS來進行sql查詢;(E)xpress——基於Node的Web開發框架;(A)agular——JS的前端開發框架,提供了宣告式的雙向資料繫結;(N)ode——基於V8的執行時環境(JS語言開發),可以構建快速響應、可擴充套件的網路應用。
MEAN的支持者宣稱,如果整個開發棧均能使用JS,必然會大大地提高效率,這一點毋庸置疑是一個很大的賣點。這樣一來,開發人員(無論是前端還是後端)不僅能使用一致的資料模型,在其它方面也同樣可以獲得一致的程式設計體驗。
例如,拿Mongo來說,你可以使用類JSON格式(BSON,二進位制的JSON)來儲存資料,然後在Express/Node中呼叫JSON查詢語句,再將結果以JSON格式傳給前端的Angular顯示,這樣,也自然使除錯程式容易了很多。
注意: 事實上,在MEAN架構中,前端的Angular並不是必須的,你可以將它替換成其他的前端框架,如Backbone、Ember或者Polymer。
為何選擇MongoDB?
如上所提,這個架構最重要的優勢在於能使用單一語言,這也是其選擇了Mongo的首要原因。 這裡就不討論noSQL的是與非了。一些人對MEAN架構的指責在於,MongoDB可以很好地勝任中小型的應用,但是對於大規模應用(百萬級使用者)來說可能就捉襟見肘。我想說的是,這完全取決於你如何使用它。
SQL資料庫本身是強型別的,因此可以在很大程度上保證某種層次的一致,從而確保許多型別的髒資料一開始就沒辦法進入資料庫。而NoSQL則是弱型別的資料庫,這使得它在資料驗證方面力不從心,而只能交給開發人員來實現,基於這樣的特性,它尤其適合儲存那些不規範的資料,特別是在原型開發階段,此時資料模型正在經歷快速變化。
SQL和noSQL間的技術差別,歸根結底是要在效能和穩定性間作出平衡。有些情況下,對資料的事務處理一旦設定後就不會輕易變化,那麼此時使用Mongo就非常合適;然而有時候也會涉及更為複雜的事務處理,會牽扯到許多獨立的業務邏輯,由於Mongo並沒有提供一個簡單的資料模型來支援一定級別的原子操作,因此SQL在這個時候可以派上用場。
但無論如何,不論你是否選擇MEAN中的M,你最終都需要根據自身的需求選擇出合適的工具來做正確的事情,
為何是Express?
可以簡單地把Express看成是一個在Node平臺下搭建Web應用的工具集。在Node的基礎上,它提供了許多簡潔的介面來建立請求節點、處理cookie等,此外還提供了許多功能來幫助你搭建自己的伺服器。總的來說,Express在以下幾個方面有優勢:
- 設定REST路由簡單致極:
1app.get(/account/:id, function(req, res){ /* req.params('id') is available */ }); - 支援Jade或Mustache等模板引擎
- 自動HTTP頭處理:
1app.get('/', function(req,res){ res.json({object: 'foo'}); }); - 支援Connect中介軟體,可以插入額外請求或響應處理,如使用者驗證
- 提供輔助函式解析POST請求
- 防範XSS
- 優雅的錯誤處理
如何快速上手MEAN
如果想要很快上手MEAN,那麼mean.io是一個很不錯的選擇。該專案旨在解決MEAN架構中一些常見的整合問題, 目前維護得很好,文件也很清楚,而且可以很方便地自行新增第三方庫,還能和Yeoman配合使用(通過 generator-mean by James Cryer)。
在進一步閱讀前,先假定我們同意以下觀點:(a)Mongo至少非常適合於全Javascript堆疊的原型設計;(b) 承認即使像Angular般如日中天,終有一天也會被其他的一些JS框架給取代,只要它們能幫助我們快速方便地將這個架構快速搭建起來。
接下來就要介紹Yeoman 了,它由3個你所熟知的工具構成:
- Grunt:用於生成,預覽和自動化測試你的專案,這要特別感謝由Yeoman和grin t-contrib團隊建立的許多grunt tasks。
- Bower:前端的依賴管理工具,有了它你再也不需要手動下載和管理第三方JS庫了。
- YO:快速生成一個新的應用,包括配置好你的Grunt任務以及你極有可能會用到的Bower依賴。
筆者在一年以前,曾和其他一些人建立過一個叫ExpressStack的專案,其想法很簡單,就是要提供一些工具能夠快速生成構建全JS的Web應用所需要的一切。但是,這個專案夭折了,儘管如此,許多類似的專案卻如雨後春筍般湧現出來。
下面對這些專案作些介紹:
注意: 你可能需要裝好Yeomam(npm install -g yo)和以下一些生成器(npm install -g <generator-name>)。
1. generator-angular-fullstack
這是一個AngularJS的生成器,整合了Express,可選MongoDB。主要功能如下:
- 支援客戶端和服務端的Livereload。
- Express server整合了grunt tasks。
- 內建了方便的部署流程。
- 支援Jade。
可參考: http://tylerhenkel.com/creating-apps-with-angular-and-node-using-yeoman/
另一個MEAN架構的生成器,整合了grunt-express,功能如下:
- 在generator-angular的基礎上,用express取代了Connect。
- 支援客戶端和服務端的Livereload。
- 使用app_grunt.js檔案來啟動應用,而在app.js中定義路由。
- 目錄結構基本沿襲了generator-angular的風格,只作了少許的改動。
可參考:https://github.com/Grievoushead/generator-express-angular
整合了Mongo,Express,Angular,Yeoman,Karma和Protractor(作自動測試)。
和其他的很類似,不過使用的是Mongoose和Stylus,其他的一些功能包括:
- 其目錄結構非常容易擴張(包含了一個TODO List的應用例子)
- 一個配置完整的Gruntfile,集合了livereload, linting, concatenation, minification等.
- 使用exctrl來自動掛載API。
- 使用了grunt-injector,從而無需手動修改Html的layout檔案,就可以自動裝載新新增的js和css。
- 使用Karma, Mocha和Chai來進行前端的單元測試。
該生成器非常全面,新增了許多第三方的庫,包括Passport用於使用者登入,Browserify載入js。
- 整合了AngularUI, Barbeque(用於任務佇列管理)和Bootstrap
- 整合了Bower, Browserify,Express和Font Awesome
- 整合了Grunt, Handlebars, jQuery, JSHint和Karma/Mocha
- 支援LESS/LESSHat, Livereload和Lodash/Underscore
- 整合了Modernizr, MongoDB/Mongoose和Passport
該如何做出選擇?
看了這麼多的生成器,自然要問,我該選擇哪一個呢?事實上,以上列表是有順序的,依據的是其與最新版的Yeoman的相容性以及維護的活躍度。
全Javascript的架構是否適合於產品級的應用呢?
不得不承認,如果開發堆疊的每一層都能使用JavaScript將會是一件很棒的事情(至少對於原型開發來說是這樣),然而千萬要注意,不要為了追求這一目標,而把自己而束縛住了。儘管的確有越來越多的大規模應用都在採用類似的架構,如Walmart、LinkedIn,但並不意味著模仿他們就一定能成功。
另一個需要注意的是,相對於其他的語言(如Ruby,Python或Java),在Node上搭建後端要困難得多。你可能要自己處理記憶體洩漏,避免在事件迴圈中進行耗時運算,還要非常小心異常處理,如果這些處理不當就很有可能會導致整個應用伺服器崩潰,但是這些問題在其他平臺上卻已經處理得很好了。然而,這並不是說,Node不能運用在生產環境下,當然可以,但要格外用心。
實話實說,想要“一攬子”為Web應用提供一個大而全的解決方案將非常困難,MEAN架構也肯定有其侷限性。在前端與後端的設計模式、原則和風格中有大量的演化,如果你覺得PHP或Rails是更明智的選擇,那就繼續使用下去,否則的話,不妨試試MEAN,至少在當下值得一試。