依赖管理

es6 modules

commonjs

amd

带表达式的 require 语句

如果 require 中含有表达式,由于编译时并不清楚 具体 导入了哪个模块,因此会创建一个上下文。

参考接下来的例子:假设现在有包含 .ejs 文件的如下目录结构:

example_directory
│
└───template
│   │   table.ejs
│   │   table-row.ejs
│   │
│   └───directory
│       │   another.ejs

当下面的 require() 调用被评估解析时:

require('./template/' + name + '.ejs');

webpack 解析会 require() 调用,然后提取出如下一些信息:

Directory: ./template
Regular expression: /^.*\.ejs$/

上下文模块

并且会创建一个上下文模块。它包含 对该目录下所有模块 的引用,可以使用匹配正则表达式的请求来导入这些模块。上下文模块中存在一个映射,该映射用于将请求转换为模块 ID。

示例映射:

{
  "./table.ejs": 42,
  "./table-row.ejs": 43,
  "./directory/another.ejs": 44
}

此上下文模块还包含一些访问此映射对象的运行时逻辑。

这意味着 webpack 能够支持动态导入,但会导致所有可能用到的模块都包含在 bundle 中。

require.context

可以通过 require.context() 函数实现自定义上下文。

可以给这个函数传入三个参数:要搜索的目录、是否还搜索其子目录,匹配文件的正则表达式。

webpack 会在构建中解析代码中的 require.context()

语法如下:

require.context(
  directory,
  (useSubdirectories = true),
  (regExp = /^\.\/.*$/),
  (mode = 'sync')
);

示例:

require.context('./test', false, /\.test\.js$/);
// 创建一个上下文,其中文件直接来自 test 目录,require 包含的表达式以 `.test.js` 结尾。
require.context('../', true, /\.stories\.js$/);
// 创建一个上下文,其中文件来自父文件夹及其所有子级文件夹,require 包含的表达式以 `.stories.js` 结尾。

上下文模块 API

上下文模块会导出一个接收一个参数 request 的 require 函数。

此导出函数有三个属性:resolvekeysid

  • resolve 是一个函数,它返回 request 被解析后得到的模块 id。
  • keys 也是一个函数,它返回一个数组,由所有可能被此上下文模块处理的请求组成。

如果想引入一个文件夹下面的所有文件,或者引入能匹配一个正则表达式的所有文件,这个功能就会很有帮助,例如:

function importAll(r) {
  r.keys().forEach(r);
}

importAll(require.context('../components/', true, /\.js$/));
const cache = {};

function importAll(r) {
  r.keys().forEach((key) => (cache[key] = r(key)));
}

importAll(require.context('../components/', true, /\.js$/));
// 构建时所有被导入的模块都会被填充到缓存对象中。
  • id 是上下文模块的模块 id. 它可能在使用 module.hot.accept 时会用到。

5 位贡献者

ndelangenchrisVillanuevasokrabyzykAnayaDesign