前端模塊化概述


一、為什么需要模塊化

   代碼量驟增 => 分治管理的剛性需求

 

二、模塊化方案需解決什么問題?

       模塊化要實現兩個東西:模塊加載與模塊封裝。面臨的具體問題包括:

       1、如何定義模塊以確保模塊的作用域獨立,避免命名沖突?

       2、如何管理模塊間的依賴關系,避免重復加載與循環引用?

       3、模塊化的代碼如何部署,以降低HTTP請求數?

       4、如何實現按需加載?

       5、如何在解決上述問題之后,保證性能且不影響debug?

 

三、原始的解決方案有何局限?

   命名空間 + 立即執行函數 + script標簽

   局限性:

   1、全局空間污染

   2、需手動管理依賴,不具備可擴展性

   3、無法實現按需加載

 

四、新的解決方案

1、CommonJS

       CommonJS 起源於一個服務端項目 SeverJS,該項目意在通過模塊化的開發模式, 解決 JS 作用域的問題。后來發展成了一個致力於構建 JS 生態圈的組織。

       CommonJS 提供了一套模塊加載的規范,其核心語法是通過 module.exports 暴露接口,通過 require() 加載資源。

   CommonJS 規范采用同步加載,適用於服務端,但並不適用於瀏覽器環境(網絡延遲、異步特性),因此在瀏覽器端出現了各類模塊加載器,以解決模塊加載的問題。

   各類模塊加載器提出了各自的模塊封裝的規范。其中 Sea.js 提出/實現的封裝規范,就是 CMD 規范;RequireJS 提出/實現的封裝規范,就是 AMD 規范。

 

2、Sea.js

  模塊封裝:

   define (function (require, exports, module) {

    var a = require('./a')  // 模塊加載

    a.doSomething();

    // ……

    var b = require('./b')  // 依賴可以就近書寫

    b.doSomething();

    // 通過 exports 對外提供接口

    exports.doSomething = ...

    // 或者通過 module.exports 提供整個接口

    module.exports = ...

   })

   模塊加載:

   var $ = require('jquery');

 

3、RequireJS

       模塊封裝:

   define (['./a', './b'], function(a, b) {

    a.doSomething();

    // 此處略去 100 行

    b.doSomething();

    return function () { } //返回模塊的值,可以是函數,也可以是對象

  })

  模塊加載:

  require (['./a', './b'], function (a, b) {

        // do sth

  })  

      區別

      RequireJS:依賴前置,提前加載

      Sea.js:依賴就近,延遲加載

 

4、UMD

       一種兼容 CommonJS 和 AMD 的語法糖。事實上 RequireJS 和 Sea.js 就是相互支持的。

圖片來源:https://www.leanpanda.com/blog/2015/06/28/amd-requirejs-commonjs-browserify/

      

5、打包工具:Browserify&Webpack

       在模塊化的開發方式下,模塊加載器(Module loader)解決了模塊的加載與依賴的自動管理,但是並沒有解決 HTTP 請求數的問題。如何將分散的文件合並成一個或幾個文件以減少 HTTP 請求,這就是打包工具(Module bundler)的作用。

       打包工具的核心能力是對 js 代碼進行合並,擴展能力是對 js 代碼進行優化、編譯和壓縮。webpack 的特色是擴展得比較狠,通過各類插件,可以打包任意類型的文件。

       打包工具的真正價值在哪里呢?僅僅是合並文件從而減少 HTTP 請求數嗎?當然不止,打包工具的真正價值是在工程開發中,完成從開發狀態到發布狀態的自動化構建

  減少 HTTP 請求和按需加載其實是相互矛盾的,都打包成一個文件了,自然不需要考慮模塊加載的問題。但是把所有文件都打包成一個文件,又顯得有些冗余。所以 webpack 也支持 code spliting,把文件打成多個包。

 

6、終結者:ES6 Module

      原生模塊標准得到瀏覽器全面支持之時,就是所有模塊封裝方案滅亡之日。但打包工具(自動化構建工具)仍會繼續存在。

 

五、模塊打包的技術實現

圖片來源:https://www.leanpanda.com/blog/2015/06/28/amd-requirejs-commonjs-browserify/

  以上是 browserify 的實現,webpack 的實現也差不多,這里詳細說明一下。

  首先,webpack 會將每個 js 文件編譯成一個函數:

   webpack 會將文件路徑映射為一個數字 id,入口文件默認 id 為 0,在入口文件中遇到的第一個加載的模塊,id 為 1……,總之按照加載的順序依次賦予一個 id。

    webpack 函數用於整個模塊的加載,所有模塊函數會按照 id 的順序組成一個數組,傳給 webpack 進行加載。

       最后運行的結果是:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM