真實世界的 JavaScript MVC 框架
自 HTML5 大行其道,Web 平臺也發生了很大變化,開發者開始在 JavaScript 語言中尋求創建復雜應用的解決方案。許多新的 API 應運而生,在眾多合適的場景下,瀏覽器該如何利用好這一切。
這一系列的文章 將更進一步聚焦于如何將這些強大的技術應用于實踐當中,不會創建炫酷的示例和原型,而是幫助開發者如何在項目實踐它。在 HTML5 系列文章中,我們將帶著這些流行語在專家哪里獲得如何在實踐中應用它們的方式。我們也會更進一步討論相關的技術(比如 AngularJS),并且探索未來的標準和 web 開發的趨勢。
這篇 InfoQ 文章是“Next Generation HTML5 and JavaScript”系列的一部分。你可以通過 RSS 訂閱。
隨著越來越多的邏輯在瀏覽器中執行,JavaScript 前端代碼庫變得更大也更加難維護。開發者發現了一個解決該問題的方式,即前端 MVC 框架,提高了開發效率并且更容易維護代碼。
早在 2013 年,InfoQ 已經發起了社區內 關于 JavaScript MVC 框架排行 的調查,依據它們的特點以及它們的完成度:
現在 InfoQ 向專家級實踐者發起了一次訪談,關于他們如何使用這些框架以及在開發 JavaScript 應用時使用這些框架的最佳實踐。
InfoQ:你最喜歡哪個 JavaScript MVC 框架,已經使用了多久,以及它幫你解決了那些最基本的問題?
Matteo Pagliazzi: 作為當下的框架,Angular 實至名歸,這不僅僅因為 GitHub 上獲得的贊同:它具備龐大的類庫,模塊……并且正在被很多開發者討論和使用。很明顯我們開發者很喜歡它。我覺得這和它很容易上手有關:僅僅需要 5 分鐘就能輕易地完成一個完整并且功能強大的任務。不過,隨著基礎知道到框架的核心,學習曲線變得陡峭,你會發現它非常復雜。
Julien Knebel: 在過去 2 年多的時間內,我已經使用 Ember.js 開發了 5 個 web 應用。不得不說,它給我帶來了靈活、高效還有自信,因為我可以更多的聚焦在用戶體驗,而不是在復雜的特性上投入大量的時間,比如一個強大的異步路由。
Brad Dunbar:我最喜歡 Backbone。它提供了其他類庫都不具備的簡潔和靈活。同樣,或許更重要的是,代碼的簡單易讀。
John Munsch:我最喜歡的框架是 AngularJS,我已經使用它超過了一年,并且依舊在蜜月期一樣。
我所選擇的前端框架會解決一個最基本的問題,給我以足夠的骨骼、 肌肉和結締組織,幫助我建立復雜的 UI 的前端,而不僅僅是比較。不過,相比過去的使用 JSP、PHP、Rails 等后端框架創建請求/響應的方式,這種做法更優美。
Julio Cesar Ody: 我使用 Backbone 更多一些,現在逐步使用 ReactJS 替換 Backbone 作為視圖層。
我建立的所有 web 應用完全運行在瀏覽器中,并使用 API 和/或 Websocket 與服務器通信。這意味著很多邏輯最終都使用 JavaScript 編寫,所以 Backbone 可以協助我保證代碼整潔并且可維護。
Thomas Davis: 我的第一個正式的 JavaScript MVC 項目在 2010 年末,那次我決定使用 Backbone.js 和 Sproutcore。我寫了一篇比較二者的文章,上了 Hacker News 的頭條并且獲得了超過 100,000 次點擊。基于那次反饋,我決定使用 Backbone.js。因為它的體積小,而且無須局限大規模框架的約定也不會妨礙我實現復雜的功能。在學習 Backbone.js 時,我為自己寫了一個教程幫我理解這個框架。這些文章獲得了上百萬的點擊,并且仍在增長。目前歸檔在 backbonetutorials.com。
現在創建一個應用,用戶體驗設計和保證網站正常運行一樣至關重要。單頁應用準許你創建那些傳統頁面只能通過刷新頁面無法企及的用戶體驗。比如,想象一下在你使用 非死book 時每次評論都要刷新整個頁面的情景。
InfoQ:既然有很多的替代品,你所選用的框架和其他的相比又如何?
Julien Knebel: 它表現的非常棒!我從沒想過它會讓我自己完整地編寫整個應用,盡管 Angular 也非常棒,我更在意一個框架是否能快速搭建并運行。然而我相信隨著代碼庫的增長,它可能變得更加枯燥。另一方面,在我著手學習 Ember 時遇到了很多困難,但是經過幾次“哈哈哈哈”,它們就像冬日里的積雪在陽光下慢慢融化。另外一個重點(至少對我)是“組件化“”,我不喜歡 Angular 用指令解決這個問題,Ember Component 似乎才是正確的方式。
Brad Dunbar:我發現幾乎沒有那個 JavaScript 框架可以恰好滿足應用中的所有需求。這意味著我總會圍繞它們寫一些東西。Backbone 設計的功能很少并且提供了可以相互組合的工具類,而不是增加那些幾乎用不到的功能。
John Munsch:這個問題很難回答,我的開發經驗只在 Backbone.js(大約兩年)和 AngularJS(僅僅一年)。不過,這二者我很難取舍。
Backbone.js 不錯,但是在我們共同開發一個大的項目時,最多有六個人。我們遇到了很多問題,我們使用其他類庫(雙向綁定、驗證、模板、AMD 等等)填補了 Backbone.js 在這些方面的空白。如果沒有在開始前找到填補這些空白的解決方案,那么你的同事只能選擇自己的方式。如果時間很趕并且編碼很快的話,很難找到所有的區別并 且強制統一。
我們最終完成了一個項目,并且和原來的解決方案相比更快速,不過它是一個雜交體;它的每部分都想是一個不同的動物。使用 AngularJS,這些部分大多數還是來自于框架自身并且出現這類問題的可能性也會變小。
Julio Cesar Ody:不得不說 Backbone 非常的輕量,不過這已經不是我們需要十分在意的點。一個類庫優于其他最主要的以及原因,在某些情況下開發者更喜歡使用并且在更加高產的一個。
所以在 Backbone、Angular 以及 Ember 之間,你不能選錯。我沒有把 ReactJS 包含在內,主要是因為它僅僅是一個 UI 組件庫,所以不應該把它和其他應用框架相混淆。
Thomas Davis:自 2010 年發生了很多變化。盡管我總是嘗試打破自己的舊習慣,但是目前我依舊在用 Backbone.js。它仍然是最小的并且它的理念和方法幾乎沒有改變。在我看來,它正逐步被其他競爭者所取代。Angular 這種類庫做出的努力讓開發者更加容易控制 DOM,在渲染時 Backbone.js 看起來更加的古老。與全新的模塊花 JavaScript 相比,也可以成 Backbone.js 在體積上更大。沒有任何理由將模塊、數據集、路由和視圖打包放在同一個類庫中, 相反類似 Components.js 將這些部分寫成獨立的模塊。此時還沒有真正的使用,我將在另外一個項目中考慮它。
InfoQ:創建更快、更健壯的前端很贊,但是性能如何?尤其在移動端。你們有哪些經驗?
Igor Minar:我覺得移動端依舊是 web 開發中需要考慮到的。需要給予更多的關注,Angular 很明顯在 2.0 版本中重新聚焦移動。
Julien Knebel:Ember 相比其他類庫更重,這是事實。盡管可以壓縮它,如果你打算在移動端 web 應用中使用它,一定要慎重考慮。流暢地處理 60 FPS 的動畫會很困難,你可以用 Ember 或者其他類庫實現它們。你需要了解如何處理常見的渲染上的性能問題,否則無論你選擇哪個框架都會陷入困難之中。
Brad Dunbar:相比其他類庫 Backbone 更加高效和輕量。在移動端我沒有遇到任何問題,不過我沒有為老舊的設備編寫適配。
John Munsch:我 現在的站點還沒有關注移動端,但是之前的崗位確實在移動端做了很多。因為他們需要在倉庫和棚廠區為掃碼槍運行一個額外的 web 接口。我們創建了一個附屬的 UI,僅僅是掃碼槍的一個幫助頁面。他們在桌面瀏覽器 UI 下使用相同的技術,并且頁面會調用同一個后端 API,不過掃碼槍觸屏上的頁面會更小更簡單。
在那種環境下,嘗試為已經存在的頁面創建一個響應式版本并不是一個好想法,因為在移動端可能要丟掉 80% 的功能。注意:我們非常幸運,在該項目發起前已經在 HTML5 瀏覽器下存在高質量的掃碼槍。更早之前,這種掃碼槍功能僅僅訊在與 IE5.5。
如果我現在想要回到這個項目,我要做的第一件事就是借助 Grunt 為 JavaScript 拼接、壓縮、版本等,這可以近一步加速移動端和桌面端。開啟頭部的 expires,這樣瀏覽器緩存就可以存在一個月或者更多。
Julio Cesar Ody: JavaScript 很快,現代的瀏覽器也是非常的高效并且在持續優化。
也就是說,當提到好的用戶體驗性能就是一切。不過 JavaScript 層面的事情只是一部分。如何使用 CSS(以及 transition、animation),小而美的標簽是怎樣的,這些也會影響性能。你必須關注整體。
如果你們中有人做過 C 語言中的微控制器編程,就會了解在受限的設備上編寫程序。盡管手機已經像電腦一樣強大,但它們依舊普遍上比手提電腦要慢。你承受不起過多的錯誤,并且你最好按照我前面提到的規則,加倍小心。
檢測有問題的東西會有很大幫助。首推 Chrome 開發者工具。
Thomas Davis:目 前來說,在選擇移動端和桌面端之間的前端開發方式上并不存在一個通用方法。有時,原生應用更好,有時前端 JavaScript 應用,有時服務端生成的頁面。盡管,性能問題通常與 DOM 操作相關,我敢打賭 React 將大行其道。React 實現的虛擬 DOM與瀏覽器中 DOM 相比較,僅僅在有必要時更新 DOM,達到了高性能渲染。正因為它的虛擬 DOM,你也可以在服務端渲染,在程序中訪問它們。
InfoQ:使用你所選擇的框架最有哪些獨有的工作流程?使用什么用具開發和調試?
Igor Minar:Webstorm、Karma、Chrome。
Julien Knebel:我使用 Grunt 作為構建工具預處理、預編譯、后處理、連接、壓縮等等。TextMate2 是我一直選用的 IDE。我同樣花費了大量的時間在 Chrome 開發工具上使用斷點和調試器來進行調試。當然,我離不開 Git。
Brad Dunbar:我傾向于使用那些極簡的設置,包括一個 CLI 和 vim/node/npm。最近,我正在享受 browserify 的 bundling。對于工作流程,我是很典型的編碼、刷新、調試循環往復。我從不是測試優先或同類事情的倡導者。
John Munsch:很 多前端團隊的開發者在 Mac 上使用 WebStorm 或者 Sublime。整個項目通過 Maven 構建和運行,因為后端是 Java,我們最近開始在 Maven 內部使用 Grunt 來優化前端代碼。Jsnkins 用于創建和運行單元測試,以及部署到各種測試環境和生產。
現在,有些開發者在后臺運行 Karma 跑 AngularJS 單元測試(不過目前僅僅覆蓋了 30% 的代碼)。
Julio Cesar Ody:我做了很多自己能預見到(在我參與它時)的設計。觀察一個頁面的樣子協助我對將要編寫的組件做一次內在的分析。
我用過自己編寫的Hopla,在很長一段時間內,將其作為一個構建工具。我使用 Sprockets 預處理 CoffeeScript 和 SASS,以及將應用便以為靜態 HTML/CSS/JS。這樣會很方便部署,甚至在創建 Phonegap 應用時。
然后,我經常通過使用 SCSS 編寫一個靜態 HTML 頁面開始實現一個設計,然后檢查每一部分將它們替換成 JavaScript 組件。
Thomas Davis:誠 然,我一點也不關心別人喜歡如何開發和調試,并且我的方法也會在不同的項目上發生變化。我對開發者最直截了當的建議就是使用 異步模塊定義(AMD)。Require.js 非常準確地實現了 AMD,并且在我的經驗中它使得調試所有的語言和環境都更加簡單。它不僅僅幫助你結構化你的代碼,而且減少整個代碼庫的障礙,因為一切都通過一個文件路徑 作為依賴引用。
InfoQ:隨著應用變大,保持架構的健壯以及維護龐大的代碼庫是一個挑戰。你喜歡的 JavaScript 框架有多大規模?當開發團隊膨脹并且不同的開發者需要負責不同的功能時,它的擴展性如何?
Igor Minar: 代碼重用,簡化示例代碼、樣式指南以及一些慣例用法對于壓縮龐大代碼庫的復雜性都很重要。但是在我們的日常經驗中,我們發現高質量的測試測試用例會有更大的好處,因為它們允許在低風險的情況下進行重大的重構。代碼重構是保持代碼庫整潔的關鍵之一。
Matteo Pagliazzi: 除了復雜性之外(比如服務,廠商以及供應商呈現出的混亂),Angular2 所要解決的問題,也是我最不喜歡的臟檢測機制,它用于在屬性改變時響應地更新視圖(而且這可以通過 Object.observe原生地實現,允許改變后發出通知,而不是在每次屬性變化時去檢測)。
To wrap up: Angular 非常棒,它有很了不起的社區作為后盾,有大量的外部庫可滿足每個日常需求。即便沒有找到,你也可以寫出自己的指令。不過,需要花上一定的時間去理解那些復雜的概念。
Julien Knebel: Ember 確實能處理好日漸增多的代碼庫,因為它的“強制最佳實踐”以及它的強約定,使得你需要處理很多單行代碼(也就是通過配置進行約定)。它有助于團隊的每個成 員都可以快速地 debug 其他人的代碼。我看到一些開發者因為感覺到自己代碼要受到 Ember 限制而憤怒。不過我猜真正的沮喪來自于在你想要用它嘗試一些炫酷的東西之前,必須去理解或者學習 Ember。并且我真的覺得這個額外的學習時間在長遠上看真的很值得。此外,我非常相信 Yehuda Katz 和 Tom Dale 的工作(但我想這有點主觀了)。
Brad Dunbar:我認為大型 JavaScript 代碼庫真的是一個挑戰,這和用了哪些框架無關。它需要團隊來維護一套方案,并堅持下去。借助一些模塊化方案(像我提過的 npm 和 browserify)是極好的方案。
John Munsch:目 前為止,我們在代碼規模增長上有足夠的經驗,前端 JS 規模通過優化、緩存甚至是 CDN 處理的很好。最壞的一次是嘗試在頁面上渲染上千條數據。我們也嘗試使用翻頁和其他方案解決,不過在使用翻頁以及在舊版本瀏覽器上通過大量數據生成數千個 DOM 元素的方案上我們還沒有達成一致。
其他問題實際上已經不是問題。比如,AngularJS 在切換視圖時,一個視圖保持內存占用會影響當前的視圖,它的默認行為是丟棄視圖和控制器。這是一個簡單的解決方案,可以幫助很多開發者在一個 SPA 中添加愈來愈多的功能時避免很多問題。
Julio Cesar Ody: 我認為所有的流行框架都沒有一個既定的擴展路線。它需要開發者理性地選擇。
我一直很喜歡組件或者模塊的概念。它讓我覺得寫程序就像是創建一個。每部分(或者說組件)都有它的目的,并且需要盡可能地獨立運行,暴露可以和其他組件進行交互的一小塊。
Thomas Davis:就 像我前面所提到的,只要你使用了一個模塊化 JavaScript 框架比如 Require.js,規模和維護代碼庫猶如閑庭信步,僅僅取決于代碼規范。在這點上,盡管 Backbone.js 不需要被拆分成模塊。你僅僅需要想示例那樣引入 Backbone.Model,而不用單獨地將 Backbone 作為依賴引入。
InfoQ:對你那些剛剛考慮使用一個 JavaScript 框架的團隊,有哪些常見的陷阱需要注意的么?
Matteo Pagliazzi:曾 在一個很大的開源項目中使用 Angular 作為客戶端框架,我發現經驗不夠豐富的開發者很容易陷入繼承的問題中或者使用很多對象污染了 和rootScope,這會讓應用變得很慢并且增加了瀏覽器的 RAM 占用(我們一般使用 300+ MB,一個很小的內存泄露都可能輕易地占用 1GB)。如此簡單的數據綁定確實很棒,不過你必須理解它才能更好地使用,因為它是很“神奇的”。
Julien Knebel:所 都的 MV* 框架都在前端進行比較重的 JavaScript 計算,因而應用需要為用戶輸出大量的數據,可能很快就超出了你的性能預算(假設 60 FPS 的預算)。你必須處理好翻頁、智能地滾動、明智的 CSS 聲明、細微的順序差別、下拉菜單的顯示位置等等。最終,將這些放在一起就會有非常大的影響。
Brad Dunbar: 我認為最常見的問題來自于框架中的 bug。你的客戶端需要需要測試、模塊、包管理器以及持續地整合就像服務器一樣。如果你做到了這些,應該就夠了。
John Munsch:我 之前提到過 Backbone.js 存在的問題,不過還可能會遇見一些常見的問題。比如全部在前端使用 JavaScript 生成整個頁面在 SEO 方面存在問題。很幸運,我的絕大部分工作使用了 SaaS,所以基本不用關心 SEO 的問題。不過如果你正在創建需要支持 web 爬蟲的項目,你可以去參考一下 Prerender.io、BromBone 等的解決方案,決定你該如何解決。Google Analytics 也有同樣的問題。這些問題沒有不能解決的,不過最好知道有哪些問題,需要找一個解決方案。
對我們而言,毫無疑問 IE8 是最大的問題之一。它也是唯一各個占據著大量瀏覽器市場并且沒有內建的 JavaScript 實時編譯器。結果導致了重度 JavaScript 依賴的前端應用有時會很慢。在需要展示很多數據等情況下可能導致“unresponsive script”錯誤。IE8 越早離開,對我們來說越好。
Julio Cesar Ody: 我所看到的最大的問題應該是學習曲線。很多人已經開發 web 應用程序好多年,包括服務端組件接收、處理請求以及將 HTML 返回給瀏覽器端。
這是一個完全不同的范例,和網絡編程(客戶端/服務器)有些像,并且和以前做的的那些都有些不同。它有很多和網絡編程一樣的問題,具備這方面的背景一定會有幫助的。
Thomas Davis:我 所擔心的唯一一個問題是 URL 上不存在服務端生成的內容。這理所應當就阻礙了搜索引擎抓取站點的能力,在分享頁面上也會遇到了問題。現在很多社交網絡在用戶分享功能中都會對站點進行解 析以便讀取到其他的信息。如果沒有在服務端生成內容,這些嘗試都會失敗。盡管有很多方式可以解決這個問題,不過我還是推薦 prerender.io 這個開源方案,我還寫了 SEO 服務起類庫來環節這個問題。搜索引擎巨頭們真的應該將它內置以便渲染出單頁應用的內容。有些人猜測 Google 的 Chromium 項目正在做嘗試以便可以加載和執行整個頁面。這樣就可以把它變成 Google 機器人并且識別出所有由 JavaScript 渲染出的內容。
InfoQ:如果想要開始使用一個框架,你覺得最快并且最有效的學習路徑是什么?有哪些推薦的資源么?
Igor Minar: 在 ng-newsletter.com 上有不少 Angular 方面的好書和咨詢,而且這里還有很多播客。
Julien Knebel:http://emberjs.com 官方文檔很棒,對該框架的每個特性進行了詳細解釋。另外,我在 Smashing Magazine 上寫了一個詳細的介紹(Ember 1.0 問世的時候)。非常謙虛地說,這個教程仍有很大的意義。
Brad Dunbar: 這可能不是最酷的事,不過我總會推薦閱讀源碼。這才是關鍵所在,你會知道是否它很爛。
John Munsch: 如果提問者已經很熟悉 JavaScript 了,我會推薦去完成一個小項目(四個或者更少的獨立的視圖構成一個 web 應用)并且使用剛剛討論的框架完成整個項目。創建一些東西,即便很簡單,完成的方式以及實際部署和單純“學習”一個框架還是有很大區別的。你會被強制解決 一些具體的問題并且會真正的理解一些事情,否則你可能很自然的跳過一些事情,應為學習起來它可能不那么有趣。
Julio Cesar Ody: 在喜歡的項目中可以犯很多錯誤,不過需要記下它們。我是想說,試錯和抓狂可能是個好方式,不過它不會幫助你很快地達到目的。
然后反復修改你的代碼,注意你要找到一個場景用來將很多個組件放到一起構成一個完整的應用,然后保證每一個都盡可能的獨立。
我曾經寫了一個免費的手冊,包括了 Backbone.js 的重要性,同樣是我比較推薦的教程。
Thomas Davis: 取決于你的學習方式,我通常比較喜歡跳進去然后開始鉆研。我上傳到 油Tube 上的關于 Backbone.js 是視頻教程總會收到很驚奇的反饋。
InfoQ:現在 MVC 框架已經成為主流,你覺得他們需要如何演變才能夠滿足開發者的需求?比如你覺得他們還缺少那些特性?
Igor Minar:移動端、可測試性等。
Julien Knebel:后臺和多個客戶端之間的實時數據同步可能是下一趨勢。Meteor.js 似乎正在這么做,所以我一定要盡快試一試。
Brad Dunbar: 這一點不我太確定。我傾向于給 Backbone 不足的地方提交補丁,不過并不是每一個都被采納。
John Munsch: 最簡單的答案就是參閱 ngmodules.org 這一類站點,有很多開發者反復地在這里尋求答案。任何前端有關的框架都會涉及到 HTML/CSS 框架(像 Bootstrap),文件上傳、國際化、本土化等等。如果成百上千的開發者都去探索它,在使用它上面花時間,你也就不用擔心社區分享的問題。這是簡單的 答案,不過實際上還應該有這樣兩件事,校驗以及沒有后端。
校驗
總會出現客戶端校驗的情況,并且對某些頁面來說 會很復雜。有很多頁面需要與其他頁面上的時間對比以確定它們是否在恰當的場景下出現,有些不可控因素也對其有很多限制。我們將數據通過 API 發送到服務端,將嚴格驗證的數據返回,因為你不能依賴客戶端的驗證。我們的后算不是用 JavaScript 語言編寫的,所以我們沒辦法使用同一個代碼庫來驗證,因而就需要用不同的語言寫相同的邏輯,對某些邊緣情況會出現犯同樣的錯誤的可能。
為什么不讓我描述一下 JSON 模式的數據然后使得它在客戶端以及服務端驗證上變得都很容易呢?我期待看到它可以變得更簡單。
無后端
在 去年,這是一個很火的話題(比如,nobackend.org),不過現在有些平息了。不過 觀點本身在 Firebase、Hoddie、Backendless 等技術下依舊很強勢。我認為這對僅僅熟悉前端的開發者來說是一件好事,可以不需要后端就完成一個完整的應用。這樣,很多開發者都可以輕易地創建一個應用的 前后端,這提供了更簡潔的方式來實現一個想法的原型。
Julio Cesar Ody:很難說。我認為很多想法源自于對模塊化的誤解,所以很多特性的模式只是在和以前的想法爭辯。
不過我認為 ReactJS 在這一點上很正確,它提倡組件驅動的方式來創建應用,如果你僅僅跟著示例模仿就不會出現很糟糕的錯誤。它也改善了很多難題,比如 DOM 性能,這樣確實帶來了很多便利。
這也是在創建應用時很少有人愿意花時間來解決的一類問題,所以這一步的方向很正確。
Thomas Davis:客 戶端 MVC 正沿正確的方向快速前進。我確信在這點上服務端 API 正在落后。目前,還沒有一個開發者共同遵循的既定的規范,當創建 RESTFul API 的時候客戶端數據模型和集合很難高效的獲取數據。客戶端的 Error 日志同樣需要一定的工作量,不過嘗試使用 trackjs.com 會好些。如何處理好客戶端的事件同樣有很多工作要完成。
討論會成員
Igor Minar 是一名來自 Google 的軟件工程師。他是 AngularJS 的帶頭人、測試驅動開發的實踐者、開源項目熱衷者、駭客。
Matteo Pagliazzi 是一名熱情的軟件開發者和開源貢獻者。
Julien Knebel 是一名自學的接口設計者和前端開發者,居住在巴黎。在是一個自由職業者,主要在法國的幾個最大的公司。
Brad Dunbar 是一名 JavaScript 工程師,同時也是 Backbone 和 Underscore 項目的貢獻者。
John Munsch 是一名具備 27 年開發經驗的專業軟件開發者。最近,他帶領團隊使用 AngularJS 創建新的 web 應用,在此之前的幾年內,他們使用過類型的 Backbone.js、Underscore.js 和 Handlebars.js。
Julio Cesar Ody 是一名軟件開發者、設計師、主持人并且渴望成為作家,居住在澳大利亞·悉尼。他主要工作在移動 web 開發,并且開發了一個自己很得意的實用的工具。

原文:Virtual Panel: Real-world JavaScript MVC Frameworks
來自:http://zhuanlan.zhihu.com/FrontendMagazine/20087355