webpack官網文件 :指南 -- 7.程式碼分割 - 使用import()

發表於2019-01-02

原文地址:https://webpack.js.org/guides/code-splitting-import/

動態引入

目前,一個把類函式的模組載入語法import()新增到ECMAScript的提議,正在討論中。

ES2015載入器細則定義import()為一個能在執行時動態載入ES2015模組的方法。

webpack把import()當作一個分割點,把需求的模組放到單獨的程式碼塊裡。import()把模組名當作引數,返回一個許諾:import(name) -> Promise

index.js

functiondetermineDate(){
  import('moment').then(function(moment){
    console.log(moment().format());
  }).catch(function(err){
    console.log('Failed to load moment', err);
  });
}
 
determineDate();
複製程式碼

許諾polyfill

如果你在舊瀏覽器裡使用import(),別忘了用像es6-promise或者promise-polyfill的polyfill來shim 許諾。

(譯者注:沒找到合適的詞來譯shim和polyfill,其作用是讓各版本的瀏覽器相容Javascript方法)

在你應用的入口點裡:

import Es6Promise from'es6-promise';
Es6Promise.polyfill();
// or
import'es6-promise/auto';
// or
import Promise from'promise-polyfill';
if(!window.Promise){
  window.Promise = Promise;
}
// or ...
複製程式碼

通過Babel使用

如果你想通過Babel使用import,你需要安裝或者新增syntax-dynamic-import外掛,為避免編譯錯誤它仍然在第三階段。等提議完全加到細則裡之後這將完全沒有必要。

npm install --save-dev babel-core babel-loader babel-plugin-syntax-dynamic-import babel-preset-es2015
# for this example
npm install --save moment
複製程式碼

index-es2015.js

functiondetermineDate(){
  import('moment')
    .then(moment =>moment().format('LLLL'))
    .then(str => console.log(str))
    .catch(err => console.log('Failed to load moment', err));
}
 
determineDate();複製程式碼

webpack.config.js

module.exports ={
  entry:'./index-es2015.js',
  output:{
    filename:'dist.js',
  },
  module:{
    rules:[{
      test:/\.js$/,
      exclude:/(node_modules)/,
      use:[{
        loader:'babel-loader',
        options:{
          presets:[['es2015',{modules:false}]],
          plugins:['syntax-dynamic-import']
        }
      }]
    }]
  }
};複製程式碼

不用syntax-dynamic-import外掛的話將會發生下面的編譯錯誤:

  • Module build failed: SyntaxError: 'import' and 'export' may only appear at the top

  • Module build failed: SyntaxError: Unexpected token, expected {

通過Babel和async/await使用

ES2017 async/await 和import()一起使用:

npm install --save-dev babel-plugin-transform-async-to-generator babel-plugin-transform-regenerator babel-plugin-transform-runtime複製程式碼

index-es2017.js

asyncfunctiondetermineDate(){
  const moment =awaitimport('moment');
  returnmoment().format('LLLL');
}
 
determineDate().then(str => console.log(str));
複製程式碼

webpack官網文件 :指南 -- 7.程式碼分割 - 使用import()

webpack.config.js

module.exports ={
  entry:'./index-es2017.js',
  output:{
    filename:'dist.js',
  },
  module:{
    rules:[{
      test:/\.js$/,
      exclude:/(node_modules)/,
      use:[{
        loader:'babel-loader',
        options:{
          presets:[['es2015',{modules:false}]],
          plugins:[
            'syntax-dynamic-import',
            'transform-async-to-generator',
            'transform-regenerator',
            'transform-runtime'
          ]
        }
      }]
    }]
  }
};複製程式碼

import替代require.ensuse?

好訊息:載入程式碼塊失敗的問題現在可以解決,因為他們是基於Promise。

警告:require.ensure考慮到了通過第三個引數的可選配置來簡易命名程式碼塊,但是import API還沒有提供這個功能。如果你想保留這個功能,你可以繼續使用require.ensure。

require.ensure([],function(require){
  var foo =require("./module");
},"custom-chunk-name");
複製程式碼

棄用System.import

在webpack裡,使用System.import是不符合提議細則的,所以它在v2.1.0-beta.28裡被棄用,支援import()。



相關文章