前端經常使用4種模塊化方案總結.md

JS誕生之初面向簡單頁面開發, 沒有模塊的概念。後來頁面逐漸複雜, 人類構造到 IIFE 當即執行函數來模擬 模塊;以前也有雅虎的實踐,使用命名空間 做爲模塊名。最後衍生出 面向各類使用場景 的 JS 模塊標準。例如:
面向瀏覽器的 AMD
面向Nodejs的 CommonJS
對於這種分裂狀態ES標準也在盡力彌合。 可是目前流行的實踐是 UMD模式。jquery

1 AMD

AMD 是requirejs 推廣產出的規範,主要用於瀏覽器環境,經過define和require這兩個定義模塊、調用模塊。編程

定義模塊

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
       exports.verb = function() {
           return beta.verb();
           //Or:
           return require("beta").verb();
       }
   });
//  返回對象的匿名模塊
 define(["alpha"], function (alpha) {
       return {
         verb: function(){
           return alpha.verb() + 2;
         }
       };
   });

調用模塊

require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});

define(function (require) {
        require(['a', 'b'], function (a, b) {
            //modules a and b are now available for use.
        });
    });

2 commonJS

Node 應用由模塊組成,採用 CommonJS 模塊規範。
每一個文件就是一個模塊,有本身的做用域。在一個文件裏面定義的變量、函數、類,都是私有的,對其餘文件不可見。
CommonJS 加載模塊是同步的,因此只有加載完成才能執行後面的操做。像Node.js主要用於服務器的編程,加載的模塊文件通常都已經存在本地硬盤,因此加載起來比較快,不用考慮異步加載的方式,因此CommonJS規範比較適用。但若是是瀏覽器環境,要從服務器加載模塊,這是就必須採用異步模式。因此就有了 AMD CMD 解決方案。api

// a.js
// 至關於這裏還有一行:var exports = module.exports;代碼
exports.a = 'Hello world'; // 至關於:module.exports.a = 'Hello world';

// b.js
var moduleA = require('./a.js');
console.log(moduleA.a); // 打印出hello world

3 UMD

兼容 AMD 和 commonjs,也兼容 全局變量定義的 通用的模塊化規範瀏覽器

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
     function a(){}; // 私有方法,由於它沒被返回 (見下面)
    function b(){}; // 公共方法,由於被返回了
    function c(){}; // 公共方法,由於被返回了
    // 暴露公共方法
    return {
        b: b,
        c: c
    }
}));

4 ES6 Module

ES6 在語言標準的層面上,實現了模塊功能,並且實現得至關簡單,旨在成爲瀏覽器和服務器通用的模塊解決方案。其模塊功能主要由兩個命令構成:export和import。
export命令用於規定模塊的對外接口,導出模塊暴露的api ;import命令用於輸入其餘模塊提供的功能,引入其餘模塊。緩存

/** 定義模塊 math.js **/
var basicNum = 0;
var add = function (a, b) {
    return a + b;
};
export { basicNum, add };

/** 引用模塊 **/
import { basicNum, add } from './math';
function test(ele) {
    ele.textContent = add(99 + basicNum);
}

5 ES6 模塊與 CommonJS 模塊的差別

  1. CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。
  • CommonJS 模塊輸出的是值的拷貝,也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值。
  • ES6 模塊的運行機制與 CommonJS 不同。JS 引擎對腳本靜態分析的時候,遇到模塊加載命令import,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊裏面去取值。換句話說,ES6 的import有點像 Unix 系統的「符號鏈接」,原始值變了,import加載的值也會跟着變。所以,ES6 模塊是動態引用,而且不會緩存值,模塊裏面的變量綁定其所在的模塊。
  1. CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。
  • 運行時加載: CommonJS 模塊就是對象;即在輸入時是先加載整個模塊,生成一個對象,而後再從這個對象上面讀取方法,這種加載稱爲「運行時加載」。
  • 編譯時加載: ES6 模塊不是對象,而是經過 export 命令顯式指定輸出的代碼,import時採用靜態命令的形式。即在import時能夠指定加載某個輸出值,而不是加載整個模塊,這種加載稱爲「編譯時加載」。

CommonJS 加載的是一個對象(即module.exports屬性),該對象只有在腳本運行完纔會生成。而 ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。服務器

相關文章
相關標籤/搜索