本系列文章實際上就是官網文檔的翻譯加上自己實踐過程中的理解。 伴隨著websites演化至web apps的過程,有三個現象是很明顯的: 頁面中有越來越多的Js。 客戶端能做的事情越來越多。 越來越少的頁面重載(當然也伴隨著更複雜的代碼)。 這些現象導致了什麼?大量的前端代碼。 龐大的代碼庫需要被高 ...
本系列文章實際上就是官網文檔的翻譯加上自己實踐過程中的理解。
伴隨著websites演化至web apps的過程,有三個現象是很明顯的:
- 頁面中有越來越多的Js。
- 客戶端能做的事情越來越多。
- 越來越少的頁面重載(當然也伴隨著更複雜的代碼)。
這些現象導致了什麼?大量的前端代碼。
龐大的代碼庫需要被高效的組織。而Module(組件式)開發的系統即為大多數開發者採取的途徑。
MODULE SYSTEM STYLES
有很多種定義依賴,導出變數的標準或者說方法:
- <script> tag 的形式(不通過組件系統)
- CommonJs
- Amd形式
- ES6組件
- 各種其它風格。。
<script>tag形式
在非組件系統中,我們的模塊化後的代碼是這樣被組織的。
<script src="module1.js"></script> <script src="module2.js"></script> <script src="libraryA.js"></script> <script src="module3.js"></script>
各個組件向全局變數提供了一個個介面(如:瀏覽器環境的 window對象)。之後,藉助全局對象,我們就能使用這些組件。
痛點
- 全局對象可能會有屬性間衝突(這就是Jquery提供了給$重命名途徑的原因)
- 我們需要關心組件載入的順序(先載入依賴項)
- 開發者需要花很多精力來解決依賴問題。
- 在較大的項目中,tag列表將會變得非常的大且難於維護。
CommonJs:同步式的require
這種風格的組件系統使用同步的形式來載入依賴項,並返回導出的介面。每一個組件可以藉助exports對象或者配置module.exports來導出介面(Node.js開發者再熟悉不過了)。
require("module"); require("../file.js"); exports.doStuff = function() {}; module.exports = someValue;
優點
- 適合用作後端的組件(一次性載入到Cache以重用)
- 已經有了很多此風格的組件(NPM)
- 簡單易用
痛點
- 阻塞式,不適合前端。
典例
- node.js
- browserify
- modules-webmake
- wreq
AMD:非同步式的require
AMD的全稱是Asynchronous Module Definition,很多需要用到組建式系統,但又感受到它們在前端的痛點的開發者建設了AMD。
require(["module", "../file"], function(module, file) { /* ... */ }); define("mymodule", ["dep1", "dep2"], function(d1, d2) { return someExportedValue; });
優點
- 非同步載入,適合前端環境。
- 並行載入,帶來速度提升。
痛點
- 帶來了更多的代碼工作量。
典例
- require.js
- curl.js
ES6組件
From EcmaScript6
import "jquery"; export function doStuff() {} module "localModule" {}
雖然是標準,但是被瀏覽器廣泛支持還需要一段時間。
TRANSFERRING
組件雖然被執行於客戶端,但不可避免需要經由伺服器傳送。
關於組件的傳送,有兩個極端:
- 每個組件,一個HTTP請求。
- 優點:僅僅傳送依賴項。
- 缺點:請求多,負載高,更慢的啟動延遲。
- 所有的組件,一個HTTP請求。
- 優點:更快,更低延遲。
- 傳送了沒必要傳的東西。
讓我們在兩者間做一個妥協。在大多數情況下,以下的方法將更為適用:
->在編譯所有的組件時,將組件分為多種批次(chunks or batches)。
再某個批次再被需要的時候,再發送他們。
解決了前者帶來的請求的高延遲、高負載,後者帶來的無必要信息的傳送。
那麼,問題來了,這個分批次由誰來做?
webpack。
當然,gulp,grunt也是時下很火的可選項。具體工具的選型,仁者見仁,智者見智。
WHY ONLY JAVASCRIPT?
組件化系統難道就只能為javascript服務嗎?前端還需要解決的問題有
- 樣式表
- 圖片
- 字體
- 模版
- coffeescript -> js
- less -> css
- jade -> html
- 各種。。。。。。
沒錯,這些,webpack也能搞定
require("./style.css"); require("./style.less"); require("./template.jade"); require("./image.png");