成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JS模塊化——CommonJS AMD CMD UMD ES6 Module 比較

shadowbook / 602人閱讀

摘要:即盡早地執(zhí)行依賴(lài)模塊。阮一峰輸出值的引用模塊是動(dòng)態(tài)關(guān)聯(lián)模塊中的值,輸出的是值得引用。的加載實(shí)現(xiàn)阮一峰運(yùn)行時(shí)加載靜態(tài)編譯模塊是運(yùn)行時(shí)加載,模塊是編譯時(shí)輸出接口。

模塊化開(kāi)發(fā) 優(yōu)點(diǎn)

模塊化開(kāi)發(fā)中,通常一個(gè)文件就是一個(gè)模塊,有自己的作用域,只向外暴露特定的變量和函數(shù),并且可以按需加載。

依賴(lài)自動(dòng)加載,按需加載。

提高代碼復(fù)用率,方便進(jìn)行代碼的管理,使得代碼管理更加清晰、規(guī)范。

減少了命名沖突,消除全局變量。

目前流行的js模塊化規(guī)范有CommonJS、AMD、CMD以及ES6的模塊系統(tǒng)

常見(jiàn)模塊化規(guī)范

CommonJs (Node.js)

AMD (RequireJS)

CMD (SeaJS)

CommonJS(Node.js)

CommonJS是服務(wù)器模塊的規(guī)范,Node.js采用了這個(gè)規(guī)范。

根據(jù) CommonJS 規(guī)范,一個(gè)多帶帶的文件就是一個(gè)模塊,每一個(gè)模塊都是一個(gè)多帶帶的作用域,在一個(gè)文件定義的變量(還包括函數(shù)和類(lèi)),都是私有的,對(duì)其他文件是不可見(jiàn)的。

CommonJS規(guī)范加載模塊是同步的,也就是說(shuō),只有加載完成,才能執(zhí)行后面的操作。

CommonJS 中,加載模塊使用 require 方法。該方法讀取一個(gè)文件并執(zhí)行,最后返回文件內(nèi)部的 exports 對(duì)象。

Node.js 主要用于服務(wù)器編程,加載的模塊文件一般都已經(jīng)存在本地硬盤(pán),加載起來(lái)較快,不用考慮異步加載的方式,所以 CommonJS 的同步加載模塊規(guī)范是比較適用的。

但如果是瀏覽器環(huán)境,要從服務(wù)器加載模塊,這是就必須采用異步模式。所以就有了 AMD,CMD 等解決方案。

var x = 5;
var addX = function(value) {
  return value + x;
};

module.exports.x = x;
module.exports.addX = addX;


// 也可以改寫(xiě)為如下
module.exports = {
  x: x,
  addX: addX,
};
let math = require("./math.js");
console.log("math.x",math.x);
console.log("math.addX", math.addX(4));
AMD (RequireJS) 異步模塊定義

AMD = Asynchronous Module Definition,即 異步模塊定義。

AMD 規(guī)范加載模塊是異步的,并允許函數(shù)回調(diào),不必等到所有模塊都加載完成,后續(xù)操作可以正常執(zhí)行。

AMD 中,使用 require 獲取依賴(lài)模塊,使用 exports 導(dǎo)出 API

//規(guī)范 API
define(id?, dependencies?, factory);
define.amd = {};


// 定義無(wú)依賴(lài)的模塊
define({
    add: function(x,y){
        return x + y;
    }
});


// 定義有依賴(lài)的模塊
define(["alpha"], function(alpha){
    return {
        verb: function(){
            return alpha.verb() + 1;
        }
    }
});
異步加載和回調(diào)
require([module], callback)callback 為模塊加載完成后的回調(diào)函數(shù)
//加載 math模塊,完成之后執(zhí)行回調(diào)函數(shù)
require(["math"], function(math) {
 math.add(2, 3);
});
RequireJS

RequireJS 是一個(gè)前端模塊化管理的工具庫(kù),遵循 AMD 規(guī)范,RequireJS 是對(duì) AMD 規(guī)范的闡述。

RequireJS 基本思想為,通過(guò)一個(gè)函數(shù)來(lái)將所有所需的或者所依賴(lài)的模塊裝載進(jìn)來(lái),然后返回一個(gè)新的函數(shù)(模塊)。后續(xù)所有的關(guān)于新模塊的業(yè)務(wù)代碼都在這個(gè)函數(shù)內(nèi)部操作。

RequireJS 要求每個(gè)模塊均放在獨(dú)立的文件之中,并使用 define 定義模塊,使用 require 方法調(diào)用模塊。

按照是否有依賴(lài)其他模塊情況,可以分為 獨(dú)立模塊非獨(dú)立模塊。

獨(dú)立模塊,不依賴(lài)其他模塊,直接定義

define({
    method1: function(){},
    method2: function(){}
});

//等價(jià)于
define(function() {
    return {
        method1: function(){},
        method2: function(){}
    }
});

非獨(dú)立模塊,依賴(lài)其他模塊

define([ "module1", "module2" ], function(m1, m2) {
    ...
});

//等價(jià)于
define(function(require) {
    var m1 = require("module1");
    var m2 = require("module2");
    ...
});

require 方法調(diào)用模塊

require(["foo", "bar"], function(foo, bar) {
    foo.func();
    bar.func();
});
CMD (SeaJS)

CMD = Common Module Definition,即 通用模塊定義CMDSeaJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出。

CMD規(guī)范和AMD類(lèi)似,都主要運(yùn)行于瀏覽器端,寫(xiě)法上看起來(lái)也很類(lèi)似。主要是區(qū)別在于 模塊初始化時(shí)機(jī)

AMD中只要模塊作為依賴(lài)時(shí),就會(huì)加載并初始化

CMD中,模塊作為依賴(lài)且被引用時(shí)才會(huì)初始化,否則只會(huì)加載。

CMD 推崇依賴(lài)就近,AMD 推崇依賴(lài)前置。

AMDAPI 默認(rèn)是一個(gè)當(dāng)多個(gè)用,CMD 嚴(yán)格的區(qū)分推崇職責(zé)單一。例如,AMDrequire 分全局的和局部的。CMD里面沒(méi)有全局的 require,提供 seajs.use() 來(lái)實(shí)現(xiàn)模塊系統(tǒng)的加載啟動(dòng)。CMD 里每個(gè) API 都簡(jiǎn)單純粹。

//AMD
define(["./a","./b"], function (a, b) {
 
    //依賴(lài)一開(kāi)始就寫(xiě)好
    a.test();
    b.test();
});
 
//CMD
define(function (requie, exports, module) {
     
    //依賴(lài)可以就近書(shū)寫(xiě)
    var a = require("./a");
    a.test();
     
    ...
    //軟依賴(lài)
    if (status) {
        var b = requie("./b");
        b.test();
    }
});
Sea.js

Sea.js Github Page

SeaJS與RequireJS最大的區(qū)別

使用Sea.js,在書(shū)寫(xiě)文件時(shí),需要遵守CMD(Common Module Definition)模塊定義規(guī)范。一個(gè)文件就是一個(gè)模塊。

用法

通過(guò) exports 暴露接口。這意味著不需要命名空間了,更不需要全局變量。這是一種徹底的命名沖突解決方案。

通過(guò) require 引入依賴(lài)。這可以讓依賴(lài)內(nèi)置,開(kāi)發(fā)者只需關(guān)心當(dāng)前模塊的依賴(lài),其他事情 Sea.js 都會(huì)自動(dòng)處理好。對(duì)模塊開(kāi)發(fā)者來(lái)說(shuō),這是一種很好的 關(guān)注度分離,能讓程序員更多地享受編碼的樂(lè)趣。

通過(guò) define 定義模塊,更多詳情參考SeasJS | 極客學(xué)院。

示例

例如,對(duì)于下述util.js代碼

var org = {};
org.CoolSite = {};
org.CoolSite.Utils = {};

org.CoolSite.Utils.each = function (arr) {
  // 實(shí)現(xiàn)代碼
};

org.CoolSite.Utils.log = function (str) {
  // 實(shí)現(xiàn)代碼
};

可以采用SeaJS重寫(xiě)為

define(function(require, exports) {
  exports.each = function (arr) {
    // 實(shí)現(xiàn)代碼
  };

  exports.log = function (str) {
    // 實(shí)現(xiàn)代碼
  };
});

通過(guò) exports 就可以向外提供接口。通過(guò) require("./util.js") 就可以拿到 util.js 中通過(guò) exports 暴露的接口。這里的 require 可以認(rèn)為是 Sea.js 給 JavaScript 語(yǔ)言增加的一個(gè)語(yǔ)法關(guān)鍵字,通過(guò) require 可以獲取其他模塊提供的接口。

define(function(require, exports) {
  var util = require("./util.js");
  exports.init = function() {
    // 實(shí)現(xiàn)代碼
  };
});
SeaJS與RequireJS區(qū)別

二者區(qū)別主要表現(xiàn)在模塊初始化時(shí)機(jī)

AMD(RequireJS)中只要模塊作為依賴(lài)時(shí),就會(huì)加載并初始化。即盡早地執(zhí)行(依賴(lài))模塊。相當(dāng)于所有的require都被提前了,而且模塊執(zhí)行的順序也不一定100%就是require書(shū)寫(xiě)順序。

CMD(SeaJS)中,模塊作為依賴(lài)且被引用時(shí)才會(huì)初始化,否則只會(huì)加載。即只會(huì)在模塊真正需要使用的時(shí)候才初始化。模塊加載的順序是嚴(yán)格按照require書(shū)寫(xiě)的順序。

從規(guī)范上來(lái)說(shuō),AMD 更加簡(jiǎn)單且嚴(yán)謹(jǐn),適用性更廣,而在RequireJS強(qiáng)力的推動(dòng)下,在國(guó)外幾乎成了事實(shí)上的異步模塊標(biāo)準(zhǔn),各大類(lèi)庫(kù)也相繼支持AMD規(guī)范。

但從SeaJS與CMD來(lái)說(shuō),也做了很多不錯(cuò)東西:1、相對(duì)自然的依賴(lài)聲明風(fēng)格 2、小而美的內(nèi)部實(shí)現(xiàn) 3、貼心的外圍功能設(shè)計(jì) 4、更好的中文社區(qū)支持。

UMD

UMD = Universal Module Definition,即通用模塊定義。UMDAMDCommonJS的糅合。

AMD 模塊以瀏覽器第一的原則發(fā)展,異步加載模塊。
CommonJS 模塊以服務(wù)器第一原則發(fā)展,選擇同步加載。它的模塊無(wú)需包裝(unwrapped modules)。
這迫使人們又想出另一個(gè)更通用的模式 UMD(Universal Module Definition),實(shí)現(xiàn)跨平臺(tái)的解決方案。

UMD 先判斷是否支持 Node.js 的模塊(exports)是否存在,存在則使用 Node.js 模塊模式。再判斷是否支持 AMDdefine 是否存在),存在則使用 AMD 方式加載模塊。

(function (window, factory) {
    if (typeof exports === "object") {
     
        module.exports = factory();
    } else if (typeof define === "function" && define.amd) {
     
        define(factory);
    } else {
     
        window.eventUtil = factory();
    }
})(this, function () {
    //module ...
});
ES6 模塊 ES6模塊和CommonJS區(qū)別

ES6 模塊輸出的是值的引用,輸出接口動(dòng)態(tài)綁定,而 CommonJS 輸出的是值的拷貝。

CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口。

CommonJS 輸出值的拷貝

CommonJS 模塊輸出的是值的拷貝(類(lèi)比于基本類(lèi)型和引用類(lèi)型的賦值操作)。對(duì)于基本類(lèi)型,一旦輸出,模塊內(nèi)部的變化影響不到這個(gè)值。對(duì)于引用類(lèi)型,效果同引用類(lèi)型的賦值操作。

// lib.js
var counter = 3;
var obj = {
    name: "David"
};

function changeValue() {
    counter++;
    obj.name = "Peter";
};

module.exports = {
    counter: counter,
    obj: obj,
    changeValue: changeValue,
};
// main.js
var mod = require("./lib");

console.log(mod.counter);  // 3
console.log(mod.obj.name);  //  "David"
mod.changeValue();
console.log(mod.counter);  // 3
console.log(mod.obj.name);  //  "Peter"

// Or
console.log(require("./lib").counter);  // 3
console.log(require("./lib").obj.name);  //  "Peter"

counter 是基本類(lèi)型值,模塊內(nèi)部值的變化不影響輸出的值變化。

obj 是引用類(lèi)型值,模塊內(nèi)部值的變化影響輸出的值變化。

上述兩點(diǎn)區(qū)別,類(lèi)比于基本類(lèi)型和引用類(lèi)型的賦值操作。

也可以借助取值函數(shù)(getter),將 counter 轉(zhuǎn)為引用類(lèi)型值,效果如下。

在類(lèi)的內(nèi)部,可以使用 getset 關(guān)鍵字,對(duì)某個(gè)屬性設(shè)置存執(zhí)函數(shù)和取值函數(shù),攔截該屬性的存取行為。 —— class | 阮一峰
// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  get counter() {
    return counter
  },
  incCounter: incCounter,
};
// main.js
var mod = require("./lib");

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter); // 4
ES6 輸出值的引用

ES6 模塊是動(dòng)態(tài)關(guān)聯(lián)模塊中的值,輸出的是值得引用。原始值變了,import 加載的值也會(huì)跟著變。

ES6 模塊的運(yùn)行機(jī)制與 CommonJS 不一樣。JS 引擎對(duì)腳本靜態(tài)分析時(shí),遇到模塊加載命令 import,就會(huì)生成一個(gè)只讀引用。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。ES6 模塊中,原始值變了,import 加載的值也會(huì)跟著變。因此,ES6 模塊是動(dòng)態(tài)引用,并且不會(huì)緩存值。  —— ES6 Module 的加載實(shí)現(xiàn) | 阮一峰
// lib.js
export let counter = 3;
export function incCounter() {
  counter++;
}

// main.js
import { counter, incCounter } from "./lib";
console.log(counter); // 3
incCounter();
console.log(counter); // 4
CommonJS 運(yùn)行時(shí)加載 ES6靜態(tài)編譯

CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口。

這是因?yàn)椋?strong>CommonJS 加載的是一個(gè)對(duì)象(即 module.exports 屬性),該對(duì)象只有在腳本運(yùn)行完才會(huì)生成。而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。

ES6 模塊是編譯時(shí)輸出接口,因此有如下2個(gè)特點(diǎn)

import 命令會(huì)被 JS 引擎靜態(tài)分析,優(yōu)先于模塊內(nèi)的其他內(nèi)容執(zhí)行

export 命令會(huì)有變量聲明提升的效果

import 優(yōu)先執(zhí)行

在文件中的任何位置引入 import 模塊都會(huì)被提前到文件頂部

// a.js
console.log("a.js")
import { foo } from "./b";

// b.js
export let foo = 1;
console.log("b.js 先執(zhí)行");

// 執(zhí)行結(jié)果:
// b.js 先執(zhí)行
// a.js

雖然 a 模塊中 import 引入晚于 console.log("a"),但是它被 JS 引擎通過(guò)靜態(tài)分析,提到模塊執(zhí)行的最前面,優(yōu)于模塊中的其他部分的執(zhí)行。

export 命令變量提升效果

由于 importexport 是靜態(tài)執(zhí)行,所以 importexport 具有變量提升效果。即 importexport 命令在模塊中的位置并不影響程序的輸出。

// a.js
import { foo } from "./b";
console.log("a.js");
export const bar = 1;
export const bar2 = () => {
  console.log("bar2");
}
export function bar3() {
  console.log("bar3");
}

// b.js
export let foo = 1;
import * as a from "./a";
console.log(a);

// 執(zhí)行結(jié)果:
// { bar: undefined, bar2: undefined, bar3: [Function: bar3] }
// a.js

a 模塊引用了 b 模塊,b 模塊也引用了 a 模塊,export 聲明的變量也是優(yōu)于模塊其它內(nèi)容的執(zhí)行的。但具體對(duì)變量賦值需要等到執(zhí)行到相應(yīng)代碼的時(shí)候。

ES6模塊和CommonJS相同點(diǎn) 模塊不會(huì)重復(fù)執(zhí)行

重復(fù)引入某個(gè)相同的模塊時(shí),模塊只會(huì)執(zhí)行一次。

循環(huán)依賴(lài) CommonJS 模塊循環(huán)依賴(lài)

CommonJS 模塊的重要特性是加載時(shí)執(zhí)行,即腳本代碼在 require 的時(shí)候,就會(huì)全部執(zhí)行。一旦出現(xiàn)某個(gè)模塊被“循環(huán)加載”,就只輸出已經(jīng)執(zhí)行的部分,還未執(zhí)行的部分不會(huì)輸出。

Demo 1
//a.js
exports.done = false;
var b = require("./b.js");
console.log("在 a.js 之中,b.done = %j", b.done);
exports.done = true;
console.log("a.js 執(zhí)行完畢");

上面代碼之中,a.js 腳本先輸出一個(gè) done 變量,然后加載另一個(gè)腳本文件 b.js。注意,此時(shí) a.js 代碼就停在這里,等待 b.js 執(zhí)行完畢,再往下執(zhí)行。

再看 b.js 的代碼。

//b.js
exports.done = false;
var a = require("./a.js");
console.log("在 b.js 之中,a.done = %j", a.done);
exports.done = true;
console.log("b.js 執(zhí)行完畢");

上面代碼之中,b.js 執(zhí)行到第二行,就會(huì)去加載 a.js,這時(shí),就發(fā)生了“循環(huán)加載”。系統(tǒng)會(huì) a.js 模塊對(duì)應(yīng)對(duì)象的 exports 屬性取值,可是因?yàn)?a.js 還沒(méi)有執(zhí)行完,從 exports 屬性只能取回已經(jīng)執(zhí)行的部分,而不是最后的值。

a.js 已經(jīng)執(zhí)行的部分,只有一行。

exports.done = false;

因此,對(duì)于 b.js來(lái)說(shuō),它從 a.js 只輸入一個(gè)變量 done,值為 false

然后,b.js 接著往下執(zhí)行,等到全部執(zhí)行完畢,再把執(zhí)行權(quán)交還給 a.js。于是,a.js 接著往下執(zhí)行,直到執(zhí)行完畢。我們寫(xiě)一個(gè)腳本 main.js,驗(yàn)證這個(gè)過(guò)程。

var a = require("./a.js");
var b = require("./b.js");
console.log("在 main.js 之中, a.done=%j, b.done=%j", a.done, b.done);

執(zhí)行 main.js,運(yùn)行結(jié)果如下。

$ node main.js

在 b.js 之中,a.done = false
b.js 執(zhí)行完畢
在 a.js 之中,b.done = true
a.js 執(zhí)行完畢
在 main.js 之中, a.done=true, b.done=true

上面的代碼證明了2點(diǎn)

b.js 之中,a.js 沒(méi)有執(zhí)行完畢,只執(zhí)行了第一行

main.js 執(zhí)行到第二行時(shí),不會(huì)再次執(zhí)行 b.js,而是輸出緩存的 b.js 的執(zhí)行結(jié)果,即它的第四行。

exports.done = true;

總之,CommonJS 輸入的是被輸出值的拷貝,不是引用。

另外,由于 CommonJS 模塊遇到循環(huán)加載時(shí),返回的是當(dāng)前已經(jīng)執(zhí)行的部分的值,而不是代碼全部執(zhí)行后的值,兩者可能會(huì)有差異。所以,輸入變量的時(shí)候,必須非常小心。

var a = require("a"); // 安全的寫(xiě)法 導(dǎo)入整體,保證module已經(jīng)執(zhí)行完成
var foo = require("a").foo; // 危險(xiǎn)的寫(xiě)法

exports.good = function (arg) {
  return a.foo("good", arg); // 使用的是 a.foo 的最新值
};

exports.bad = function (arg) {
  return foo("bad", arg); // 使用的是一個(gè)部分加載時(shí)的值
};

上面代碼中,如果發(fā)生循環(huán)加載,require("a").foo 的值很可能后面會(huì)被改寫(xiě),改用 require("a") 會(huì)更保險(xiǎn)一點(diǎn)。

Demo 2
// a.js
console.log("a starting");
exports.done = false;
const b = require("./b");
console.log("in a, b.done =", b.done);
exports.done = true;
console.log("a done");

// b.js
console.log("b starting");
exports.done = false;
const a = require("./a");
console.log("in b, a.done =", a.done);
exports.done = true;
console.log("b done");

// node a.js
// 執(zhí)行結(jié)果:
// a starting
// b starting
// in b, a.done = false
// b done
// in a, b.done = true
// a done

從上面的執(zhí)行過(guò)程中,可以看到,在 CommonJS 規(guī)范中,當(dāng)遇到 require() 語(yǔ)句時(shí),會(huì)執(zhí)行 require 模塊中的代碼,并緩存執(zhí)行的結(jié)果,當(dāng)下次再次加載時(shí)不會(huì)重復(fù)執(zhí)行,而是直接取緩存的結(jié)果。正因?yàn)榇耍霈F(xiàn)循環(huán)依賴(lài)時(shí)才不會(huì)出現(xiàn)無(wú)限循環(huán)調(diào)用的情況。

ES6 模塊循環(huán)依賴(lài)

跟 CommonJS 模塊一樣,ES6 不會(huì)再去執(zhí)行重復(fù)加載的模塊,又由于 ES6 動(dòng)態(tài)輸出綁定的特性,能保證 ES6 在任何時(shí)候都能獲取其它模塊當(dāng)前的最新值。

動(dòng)態(tài) import()

ES6 模塊在編譯時(shí)就會(huì)靜態(tài)分析,優(yōu)先于模塊內(nèi)的其他內(nèi)容執(zhí)行,所以導(dǎo)致了我們無(wú)法寫(xiě)出像下面這樣的代碼

if(some condition) {
  import a from "./a";
}else {
  import b from "./b";
}

// or 
import a from (str + "b");

因?yàn)榫幾g時(shí)靜態(tài)分析,導(dǎo)致了我們無(wú)法在條件語(yǔ)句或者拼接字符串模塊,因?yàn)檫@些都是需要在運(yùn)行時(shí)才能確定的結(jié)果在 ES6 模塊是不被允許的,所以 動(dòng)態(tài)引入import() 應(yīng)運(yùn)而生。

import() 允許你在運(yùn)行時(shí)動(dòng)態(tài)地引入 ES6 模塊,想到這,你可能也想起了 require.ensure 這個(gè)語(yǔ)法,但是它們的用途卻截然不同的。

require.ensure 的出現(xiàn)是 webpack 的產(chǎn)物,它是因?yàn)闉g覽器需要一種異步的機(jī)制可以用來(lái)異步加載模塊,從而減少初始的加載文件的體積,所以如果在服務(wù)端的話(huà), require.ensure 就無(wú)用武之地了,因?yàn)榉?wù)端不存在異步加載模塊的情況,模塊同步進(jìn)行加載就可以滿(mǎn)足使用場(chǎng)景了。 CommonJS 模塊可以在運(yùn)行時(shí)確認(rèn)模塊加載。

import() 則不同,它主要是為了解決 ES6 模塊無(wú)法在運(yùn)行時(shí)確定模塊的引用關(guān)系,所以需要引入 import()

先來(lái)看下它的用法

動(dòng)態(tài)的 import() 提供一個(gè)基于 PromiseAPI

動(dòng)態(tài)的 import() 可以在腳本的任何地方使用 import() 接受字符串文字,可以根據(jù)需要構(gòu)造說(shuō)明符

// a.js
const str = "./b";
const flag = true;
if(flag) {
  import("./b").then(({foo}) => {
    console.log(foo);
  })
}
import(str).then(({foo}) => {
  console.log(foo);
})

// b.js
export const foo = "foo";

// babel-node a.js
// 執(zhí)行結(jié)果
// foo
// foo

當(dāng)然,如果在瀏覽器端的 import() 的用途就會(huì)變得更廣泛,比如 按需異步加載模塊,那么就和 require.ensure 功能類(lèi)似了。

因?yàn)槭腔?Promise 的,所以如果你想要同時(shí)加載多個(gè)模塊的話(huà),可以是 Promise.all 進(jìn)行并行異步加載。

Promise.all([
  import("./a.js"),
  import("./b.js"),
  import("./c.js"),
]).then(([a, {default: b}, {c}]) => {
    console.log("a.js is loaded dynamically");
    console.log("b.js is loaded dynamically");
    console.log("c.js is loaded dynamically");
});

還有 Promise.race 方法,它檢查哪個(gè) Promise 被首先 resolvedreject。我們可以使用 import() 來(lái)檢查哪個(gè) CDN 速度更快:

const CDNs = [
  {
    name: "jQuery.com",
    url: "https://code.jquery.com/jquery-3.1.1.min.js"
  },
  {
    name: "googleapis.com",
    url: "https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"
  }
];

console.log(`------`);
console.log(`jQuery is: ${window.jQuery}`);

Promise.race([
  import(CDNs[0].url).then(()=>console.log(CDNs[0].name, "loaded")),
  import(CDNs[1].url).then(()=>console.log(CDNs[1].name, "loaded"))
]).then(()=> {
  console.log(`jQuery version: ${window.jQuery.fn.jquery}`);
});

當(dāng)然,如果你覺(jué)得這樣寫(xiě)還不夠優(yōu)雅,也可以結(jié)合 async/await 語(yǔ)法糖來(lái)使用。

async function main() {
  const myModule = await import("./myModule.js");
  const {export1, export2} = await import("./myModule.js");
  const [module1, module2, module3] =
    await Promise.all([
      import("./module1.js"),
      import("./module2.js"),
      import("./module3.js"),
    ]);
}

動(dòng)態(tài) import() 為我們提供了以異步方式使用 ES 模塊的額外功能。

根據(jù)我們的需求動(dòng)態(tài)或有條件地加載它們,這使我們能夠更快,更好地創(chuàng)建更多優(yōu)勢(shì)應(yīng)用程序。

webpack中加載3種模塊 | 語(yǔ)法

Webpack允許使用不同的模塊類(lèi)型,但是底層必須使用同一種實(shí)現(xiàn)。所有的模塊可以直接在盒外運(yùn)行。

ES6 模塊

import MyModule from "./MyModule.js";

CommonJS(Require)

var MyModule = require("./MyModule.js");

AMD

define(["./MyModule.js"], function (MyModule) {
});
參考資料

AMD, CMD, CommonJS和UMD | Segmentfault

JS模塊化加載之CommonJS、AMD、CMD、ES6

ES6 module的加載和實(shí)現(xiàn) | 阮一峰

前端模塊化開(kāi)發(fā)方案小對(duì)比

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/109292.html

相關(guān)文章

  • js中的塊化——commonjs,AMD,CMD,UMD,ES6

    摘要:若不存在則模塊標(biāo)識(shí)應(yīng)該默認(rèn)定義為在加載器中被請(qǐng)求腳本的標(biāo)識(shí)。這也是目前很多插件頭部的寫(xiě)法,就是用來(lái)兼容各種不同模塊化的寫(xiě)法。語(yǔ)句輸出的值是動(dòng)態(tài)綁定的,綁定其所在的模塊。 前言 歷史上,js沒(méi)有模塊化的概念,不能把一個(gè)大工程分解成很多小模塊。這對(duì)于多人開(kāi)發(fā)大型,復(fù)雜的項(xiàng)目形成了巨大的障礙,明顯降低了開(kāi)發(fā)效率,java,Python有import,甚至連css都有@import,但是令人費(fèi)...

    qpal 評(píng)論0 收藏0
  • JS常見(jiàn)塊化規(guī)范(CommonJS/AMD/CMD/UMD/ES6 Module)

    摘要:常見(jiàn)模塊化方案是由社區(qū)提出的模塊化方案中的一種,遵循了這套方案。是模塊化規(guī)范中的一種,遵循了這套規(guī)范。中的模塊化能力由兩個(gè)命令構(gòu)成和,命令用于規(guī)定模塊的對(duì)外接口,命令用于輸入其他模塊提供的功能。 為什么需要模塊化 在ES6出現(xiàn)之前,JS語(yǔ)言本身并沒(méi)有提供模塊化能力,這為開(kāi)發(fā)帶來(lái)了一些問(wèn)題,其中最重要的兩個(gè)問(wèn)題應(yīng)當(dāng)是全局污染和依賴(lài)管理混亂。 // file a.js var name =...

    walterrwu 評(píng)論0 收藏0
  • JS模塊規(guī)范:AMD、UMD、CMD、commonJS、ES6 module

    摘要:要想讓模塊再次運(yùn)行,必須清除緩存。模塊加載會(huì)阻塞接下來(lái)代碼的執(zhí)行,需要等到模塊加載完成才能繼續(xù)執(zhí)行同步加載。環(huán)境服務(wù)器環(huán)境應(yīng)用的模塊規(guī)范是參照實(shí)現(xiàn)的。這等同在每個(gè)模塊頭部,有一行這樣的命令。 commonJS 特點(diǎn): 1、模塊可以多次加載,但是只會(huì)在第一次加載時(shí)運(yùn)行一次,然后運(yùn)行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果。要想讓模塊再次運(yùn)行,必須清除緩存。2、模塊加載會(huì)阻塞接下來(lái)代...

    _ang 評(píng)論0 收藏0
  • JS基礎(chǔ)】一文看懂前端塊化規(guī)范

    摘要:參考資料前端模塊化詳解完整版入門(mén)近一萬(wàn)字的語(yǔ)法知識(shí)點(diǎn)補(bǔ)充徹底搞清楚中的和和詳解 前言 前端的模塊化之路經(jīng)歷了漫長(zhǎng)的過(guò)程,想詳細(xì)了解的小伙伴可以看浪里行舟大神寫(xiě)的前端模塊化詳解(完整版),這里根據(jù)幾位大佬們寫(xiě)的文章,將模塊化規(guī)范部分做了匯總和整理,希望讀完的小伙伴能有些收獲,也希望覺(jué)得有用的小伙伴可以點(diǎn)個(gè)贊,筆芯。 什么是模塊 將一個(gè)復(fù)雜的程序依據(jù)一定的規(guī)則(規(guī)范)封裝成幾個(gè)塊(文件)...

    HelKyle 評(píng)論0 收藏0
  • 談?wù)?em>Js前端塊化規(guī)范

    摘要:依賴(lài)全部加載完成后,調(diào)用回調(diào)函數(shù)規(guī)范異步加載模塊規(guī)范和很相似,簡(jiǎn)單,并與和的規(guī)范保持了很大的兼容性在規(guī)范中,一個(gè)模塊就是一個(gè)文件。 拋出問(wèn)題: 在開(kāi)發(fā)中在導(dǎo)入模塊時(shí)經(jīng)常使用require和import; 導(dǎo)出模塊時(shí)使用module.exports/exports或者export/export default; 有時(shí)候?yàn)榱艘靡粋€(gè)模塊會(huì)使用require奇怪的是也可以使用import?...

    Steve_Wang_ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<