1. 程式人生 > >前端模塊化開發解決方案詳解

前端模塊化開發解決方案詳解

暴露 可見 返回 異步加載 def 今天 htm 硬盤 業務邏輯

一、模塊化開發方案

前端發展到今天,已經有不少模塊化的方案,比如

CommonJS(常用在服務器端,同步的,如nodejs)

AMD(常用在瀏覽器端,異步的,如requirejs)(Asynchronous Module Definition)

CMD(常用在瀏覽器端,異步的,如seajs

UMD(AMD&& CommonJS) 這些模塊化規範的核心價值都是讓 JavaScript 的模塊化開發變得簡單和自然。

技術分享圖片

服務器端模塊 在服務器端,所有的模塊都存放在本地硬盤,可以同步加載完成,等待時間就是硬盤的讀取時間。

瀏覽器端模塊: 在瀏覽器端,所有的模塊都放在服務器端,同步加載,等待時間取決於網速的快慢,可能要等很長時間,瀏覽器處於"假死"狀態。因此,瀏覽器端的模塊,不能采用"同步加載"(synchronous),只能采用"異步加載

"(asynchronous)。

二、CommonJs

CommonJs 是服務器端模塊的規範,Node.js采用了這個規範。 CommonJS 加載模塊是同步的,所以只有加載完成才能執行後面的操作。 像Node.js主要用於服務器的編程,加載的模塊文件一般都已經存在本地硬盤,所以加載起來比較快,不用考慮異步加載的方式,所以CommonJS規範比較適用。

CommonJS模塊的特點如下: 所有代碼都運行在模塊作用域,不會汙染全局作用域。 模塊可以多次加載,但是只會在第一次加載時運行一次,然後運行結果就被緩存了,以後再加載,就直接讀取緩存結果。 模塊加載的順序,按照其在代碼中出現的順序。

CommonJS語法

1、定義模塊

根據CommonJS規範,每個文件就是一個模塊,有自己的作用域。在一個文件裏面定義的變量、函數、都是私有的,對其他文件不可見。如果想在多個文件分享變量,必須定義為頂層對象的屬性,如:global.warning = true;上面代碼的warning變量,可以被所有文件讀取。當然,這樣寫法是不推薦的。

2、模塊的接口

CommonJS規範規定,每個模塊內部,module變量代表當前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,其實是加載該模塊的module.exports屬性。

3、加載模塊

加載模塊使用require

方法,該方法讀取一個文件並執行,返回文件內部module.exports對象 註:不同的實現對require時的路徑有不同要求,一般情況可以省略js拓展名,可以使用相對路徑,也可以使用絕對路徑,甚至可以省略路徑直接使用模塊名(前提是該模塊是系統內置模塊)

技術分享圖片

三、AMD

AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義". RequireJS是一個工具庫,主要用於客戶端的模塊管理。它可以讓客戶端的代碼分成一個個模塊,實現異步或動態加載,從而提高代碼的性能和可維護性。它的模塊管理遵守AMD規範。 RequireJS的基本思想是,通過define方法,將代碼定義為模塊;通過require方法,實現代碼的模塊加載。 首先,將require.js嵌入網頁,然後就能在網頁中進行模塊化編程了。 <script data-main="scripts/main" src="scripts/require.js"></script> 上面代碼的data-main屬性可省略,用於指定主代碼所在的腳本文件,在上例中為scripts子目錄下的main.js文件。用戶自定義的代碼就放在這個main.js文件中。

AMD語法

1、定義模塊

define(id?, dependencies?, factory);

id:可選參數,用來定義模塊的標識,如果沒有提供該參數,腳本文件名(去掉拓展名)

dependencies:是一個數組,表示當前模塊的依賴

factory:工廠方法,模塊初始化要執行的函數或對象。如果為函數,它應該只被執行一次。如果是對象,此對象應該為模塊的輸出值

2、加載模塊

require([dependencies], function(){}); 第一個參數是一個數組,表示所依賴的模塊,第二個參數是一個回調函數,當前面指定的模塊都加載成功後,它將被調用。加載的模塊會以參數形式傳入該函數,從而在回調函數內部就可以使用這些模塊

技術分享圖片

四、CMD

CMD 即Common Module Definition通用模塊定義 CMD規範是國內發展出來的,CMD有個瀏覽器的實現SeaJS 在 CMD 規範中,一個模塊就是一個文件。

Sea.js 是一個成熟的開源項目,核心目標是給前端開發提供簡單、極致的模塊化開發體驗。這裏不多做介紹,有興趣的可以查看官方文檔。 使用 Sea.js,在書寫文件時,需要遵守 CMD (Common Module Definition)模塊定義規範。一個文件就是一個模塊。 首先要在頁面中引入 sea.js 文件,這一般通過頁頭全局把控,也方便更新維護。想在頁面中使用某個組件時,只要通過 seajs.use 方法調用。

CMD語法

1、定義模塊 define(id?, deps?, factory)

字符串id為模塊標識,數組deps為模塊依賴; 參數 factory 可以是一個函數,也可以為對象或者字符串。

factory是一個函數,有三個參數: require 是一個方法,接受 模塊標識 作為唯一參數,用來獲取其他模塊提供的接口:require(id) exports 是一個對象,用來向外提供模塊接口 module 是一個對象,上面存儲了與當前模塊相關聯的一些屬性和方法 註: 帶 id 和 deps 參數的 define 用法不屬於 CMD 規範,而屬於 Modules/Transport 規範。

技術分享圖片

Sea.js 帶來的兩大好處: 通過 exports 暴露接口。這意味著不需要命名空間了,更不需要全局變量。這是一種徹底的命名沖突解決方案。 通過 require 引入依賴。這可以讓依賴內置,開發者只需關心當前模塊的依賴,其他事情 Sea.js 都會自動處理好。對模塊開發者來說,這是一種很好的 關註度分離,能讓程序員更多地享受編碼的樂趣。

五、AMD與CMD的區別

1.AMD推崇依賴前置。 在定義模塊的時候就要聲明其依賴的模塊; CMD推崇依賴就近,只有在用到某個模塊的時候再去require ;

2.AMD依賴模塊的執行順序和書寫順序不一定一致;CMD模塊的執行順序和書寫順序是完全一致的

3.對於依賴的模塊AMD是提前執行,CMD是延遲執行。不過RequireJS從2.0開始,也改成可以延遲執行(根據寫法不同,處理方式不通過)。

六、UMD: 通用模塊規範

UMD (Universal Module Definition)通用模塊規範 是AMD和CommonJS兩者的結合 這個模式中加入了當前存在哪種規範的判斷,所以能夠“通用”,它兼容了AMDCommonJS,同時還支持老式的“全局”變量規範: 應用UMD規範的js文件其實就是一個立即執行函數。在執行UMD規範時,會優先判斷是當前環境是否支持AMD環境,然後再檢驗是否支持CommonJS環境,否則認為當前環境為瀏覽器環境( window )。當然具體的判斷順序其實是可以調換的。

技術分享圖片

六、前端模塊化的優缺點

1、更好的分離

如果要加載多個就得放置多個 script 標簽,如果是加載模塊的話,對於 HTML 和 JavaScript 分離很有好處,在某些場景下這個分離度很重要。

2、更好的代碼組織方式 如果單個文件越來越大,維護起來出問題的幾率也會越來越大,如果是多人開發,不同的代碼風格,超多的業務邏輯混雜在一起,不要說維護了,光想想感覺都很麻煩。模塊式的開發,一個文件就是一個模塊,控制了文件的粒度,每個模塊可以專註於一個功能。

3、按需加載

4、避免命名沖突

5、更好的依賴處理

前端模塊化開發解決方案詳解