Things I Learned (Configuration)

webpack dynamic import🔗

Configuration

使用 import 函数引入的代码,在 Webpack 中会被编译到一个异步模块中。import 函数返回一个 Promise,会在异步模块 加载完毕后 resolve。

Webpack 允许在调用 import 的时候加入注释来对异步加载进行配置。最常见的是指定新文件的 chunk name:

import('module-path-here' /* webpackChunkName: "name" */);

如果在 Webpack 的配置中指定了输出的文件名格式,比如 [name].js,那么最终输出的结果的文件名就会是 name.js

当然,import 输入的参数字符串可以不是一个固定值。比如:

import('module-parent-path' + moduleName);

在这种情况下,Webpack 会尝试将 module-parent-path 下所有的文件都各自打包成一个异步模块。在这种情况下,显然 webpackChunkName 没法直接写死一个字符串了。Webpack 提供了 indexrequest 两个参数,可以用于动态生成的这些异步加载模块的命名。比如:

import(
  'module-parent-path' + moduleName
  /* webpackChunkName: "name-[index]-[request]" */
);

其中,index 表示当前引用的文件的序号,request 则表示当前引用的模块中动态的部分。举例俩说,上面这里如果 moduleNameexample,且配置生成的文件名是 [name].js,那么最终这个模块的文件名就是 name-0-example.js

当然,一次性将 module-parent-path 下所有的文件都打包成独立的异步模块可能会太多了,Webpack 提供了一些裁剪的方案:

  • webpackInclude,允许配置一个正则表达式,匹配的部分才打包成异步模块,忽略其他的
  • webpackExclude,允许配置一个正则表达式,匹配的部分会被忽略,打包其他剩下的模块
  • webpackMode,默认的模式是 lazy,每一个文件都会打包成一个异步模块;lazy-once 则会要求 Webpack 将所有的文件打包到一个模块中;eager 会把模块打包到当前的 chunk 中,但是不执行,等到真正执行了 import 命令之后,才执行里面的代码(省去了网络请求),依然返回的是 promise;weak 不会产生网络请求,默认模块会由其他途径加载完成,如果其他途径没有事先加载过,那么此处调用就会造成 promise 的 reject。

如果有多个配置,可以叠加写在一起。一个例子:

import(
  'module-parent-path' + moduleName
  /* webpackChunkName: "name-[index]-[request]" */
  /* webpackInclude: /include\.js$/ */
  /* webpackExclude: /exclude\.js$/ */
  /* webpackMode: "lazy" */
);

除了上述之外,Webpack 还支持一些模块加载相关的配置,比如:

import('module-path-here' /* webpackPrefetch: true */);

可以指定当前的异步加载模块需要 prefetch 的支持。运行时,Webpack 会向 head 中插入一个 <link rel=prefetch />

import('module-path-here' /* webpackPreload: true */);

可以指定当前的异步加载模块需要 preload 的支持。运行时,Webpack 会向 head 中插入一个 <link rel=preload />

一个例子:

import(
  /* webpackPreload: true */
  /* webpackChunkName: "name" */
  'module-path-here'
);

注意到,这里配置注释写在前面还是写在后面都是不影响的。

参考