webpack官网文档 :指南 -- 7.代码分割 - 使用import()

2,419 阅读2分钟

原文地址: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.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()。