Dynamic imports with webpack

問題

使用 webpack 構建, 動態去加載 css 時,爲何使用 import() 會報錯,使用 System.import() 能夠?css

$ webpack => 2.6.1

dynamic-load-css-file
dynamic-load-css-file-error


緣由

require.ensure()

在 webpack1.x 中提供了 require.ensure() 方法動態導入文件,其函數簽名以下:html

require.ensure(dependencies, callback, chunkName)

簡單示例:webpack

require.ensure([], function(require) {
  const foo = require("./module");
});

注:require.ensure() 出自 CommonJS 中有一個 Modules/Async/A 規範,該規範定義了 require.ensure 語法。webpack 基於此基礎,在打包的時候根據 require.ensure() 進行代碼切分,並異步加載切分後的代碼。git

System.import()

ES6 Loader 規範定義了 System.import 方法,用於在運行時動態加載 ES6 模塊,Webpack 把 System.import 做爲拆分點;因此也能夠經過 System.import() 方法實現動態引入,與 require.ensure()
不一樣的是 System.import() 返回的是一個 Promise,如:es6

System.import("./module")
  .then(module => console.log(module))
  .catch(err => console.log(Chunk loading failed))

import()

而在 webpack v2 (v2.1.0-beta.28) 廢棄了 System.import() 方法,在 webpack v3 會徹底刪除System.import() 方法, 進而支持 ECMAScript State 3 草案階段的原生 import() 方法來替代 System.import() 方法。github

import("./module").then(module => {
    return module.default;
  }).catch(err => {
    console.log("Chunk loading failed");
  });

import

ES6 模塊與 CommonJS 模塊的差別 ,自行理解:web

  • CommonJSsegmentfault

    • CommonJS 和 AMD 模塊是運行時加載瀏覽器

    • CommonJS 模塊就是對象,輸入時必須查找對象屬性緩存

    • CommonJS 模塊輸出的是值的緩存,不存在動態更新

  • ES6 Module

    • ES6 模塊是編譯時加載

    • ES6 模塊不是對象,而是經過 export 命令顯式指定輸出的代碼,再經過 import 命令輸入

    • ES6 export 語句輸出的接口,與其對應的值是動態綁定關係

因爲 ES6 中的模塊是編譯時加載,import 命令會被 JavaScript 引擎靜態分析,先於模塊內的其餘模塊執行。因此,下面的代碼會報錯:

// 報錯
if (x === 2) {
  import MyModual from './myModual';
}

注:在 Webpack 2(v2.2.0-rc.5) 中增長對 ES6 模塊的原生支持。這意味着 Webpack 如今能夠識別 import 和 export,不須要先把它們轉換成 CommonJS 模塊的格式。

require()、import、import()

require() 是 CommonJS 的實現,用於運行時加載,推薦閱讀 require() 源碼解讀

import 是 ECMAScript 6 Module 的語法,import 是靜態執行,推薦閱讀 import 命令

import() 函數是 ECMAScript Stage 3 草案階段的語法;用於完成動態加載即運行時加載,能夠用在任何地方。import()函數 返回的是一個 Promise。相似於 CommonJs 的 require() ,區別主要是前者是異步加載,後者是同步加載,推薦閱讀 proposal-dynamic-import

import() 的適用場景:

  • 按需加載

  • 條件加載

  • 動態的模塊路徑

結論

webpack 的 Dynamic Imports 實現主要是利用 ECMAScript的 import() 動態加載特性,而 import() 目前只是一個草案,若是須要用此方法,須要引入對應的轉換器,如 babel-plugin-syntax-dynamic-import

模塊化的實現對比

CommonJS AMD CMD ES6 Module
解決的問題 模塊化開發 模塊化開發 模塊化開發 模塊化開發
適用環境 服務端 瀏覽器 瀏覽器 瀏覽器/服務端
加載方式 同步加載/異步加載 異步加載 異步加載 同步加載/異步加載
模塊定義 module.exports define(id?,dependencies?,factory) define(function(require,exports,module){ }) export
模塊加載 require()/require.ensure() require([module], callback) require(module) import / import()
執行時機 提早執行 延遲執行
依賴原則 依賴前置 依賴就近
規範化的實現 require.js SeaJS
webpack 的支持 require.ensure() require() import / import()

參考

推薦閱讀

相關文章
相關標籤/搜索