一、什麼是模塊(module)?
前端領域的模塊一般指JavaScript模塊,往往表現爲一個單獨的js文件,對外暴露一些屬性和方法。
注意區分:“模塊”和“組件”
組件往往是業務層面的,可以看成一個可獨立使用的功能實現,往往表現爲一個UI部件(並不絕對),如下拉菜單等。一個組件包含其所需要的所有資源,包括邏輯(JavaScript)、樣式(CSS)、模板(HTML/Template),甚至字體和圖片。
二、爲什麼要使用模塊?
有了模塊,我們就可以方便的使用別人的代碼,想要使用什麼功能,就加載什麼模塊。
三、前端開發中的模塊化方案?
ES6之前:社區通過各種約定和妥協實現了模塊化的特徵。主要方案有AMD(用於瀏覽器)和CommonJS(用於服務器)
ES6出現之後,ES6模塊完全可以取代AMD和CommonJS,成爲瀏覽器和服務器通用的模塊解決方案。ES6模塊的設計思想是儘量靜態化,在編譯時就確定模塊的依賴關係,以及輸入輸出的變量。AMD和CommonJS在運行時才能確定這些東西。
1、CommonJS
實質:CommonJS模塊是對象,輸入時必須查找對象屬性
Node採用CommonJS模塊格式,瀏覽器不支持CommonJS格式,要想使瀏覽器支持CommonJS格式,可以使用Browserify(一個CommonJS轉化工具,讓CommonJS格式的模塊可以運行在瀏覽器端)
CommonJS模塊的輸出:
//a.js:
module.exports={
foo:'Hello',
bar:'world'
}
node會將module.exports視作默認輸出,等價於
export default{
foo:"Hello",
bar:"world"
}
加載CommonJS模塊:
(1)require
let {foo,bar}=require("a.js");
等價於:
let _fs=require("a.js");
let foo=_fs.foo;
let bar=_fs.bar;
過程:整體加載a.js模塊(加載模塊內的所有變量、方法等),生成一個對象,再從對象上讀取想要加載的變量和方法。
這種加載成爲“運行時加載”,因爲只有在運行時才能得到這個對象,導致完全沒辦法在編譯時進行“靜態優化”
(2)import
import baz from "a.js"
//baz={foo:"Hello",bar:"world"}
相當於
import {default as baz } from "a.js"
另一種寫法:
import * as baz from "a.js"
//baz.default={foo:"Hello",bar:"world"}
2、AMD
AMD是”Asynchronous Module Definition”的縮寫,意思就是”異步模塊定義”。它採用異步方式加載模塊,模塊的加載不影響它後面語句的運行。所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成之後,這個回調函數纔會運行。AMD採用require語句加載模塊,
require([module],callback)
實現AMD規範的庫:require.js、curl.js
require.js的用法請參考:require.js的用法,之前在項目中也嘗試過require.js的運用,請參考:require.js在項目中的運用
3、ES6模塊
ES6模塊實現較爲簡單,使用編譯時加載,使靜態分析成爲可能。
ES6模塊自動採用嚴格模式,嚴格模式下的限制請參考:JavaScript嚴格模式詳解,尤其要注意,在ES6模塊中,頂層this指向undefined,因此不應該在ES模塊中使用this。
參考:阮一峯 Module的語法、Module的加載實現