require.context的白话版讲解

webpack打包完成之后会产生一个类似于这样的数据结构:

{
"0": "module3"
"1": "module1"
"2": "module2"
"3": "module3"
...
}

当你代码中出现require('./module1'),打包时就会为module1生成id1,当需要导入模块的时候,就会按照id寻找对应模块,即通过id识别模块并去执行模块中的代码。这个按照id去导包的函数在源码中叫做__webpack_require__

本来一切妥妥的,偏偏有些情况下,打包过程并不能确定id。

比如下面这样,如果这个模块名是逻辑判断出来的,在webpack打包过程中是确定不了的,只有js代码执行到这一行的时候才能确定到底要导入哪个(运行时)。

require('module' + Date.now() % 4);

所以webpack想出了这样一个方法:

打包的时候将匹配到指定规则(本文中即’module’开头)的都导入进来,给他们赋值id,形成以下的数据结构

{
module0: 0,
module1: 1,
module2: 2,
module3: 3,
}

这样,当在运行时确定了模块名的时候,比如确定了是module2,那么就可以根据module2来找到其对应的id也就是2,这样就又可以像开始那样根据id找到对应模块代码去执行了(即调用__webpack_require__导包执行代码)。

好了思路理清楚了,我们来看下官方那段把人绕晕的代码:

// 这段代码的目的是为了批量导入components目录下的以.js为后缀的模块。
function importAll (r) {
  r.keys().forEach(r);
}

importAll(require.context('../components/', true, /\.js$/));

require.context('../components/', true, /\.js$/) 返回了r,这个r其实是__webpack_require__的又一层封装,很简单,他维护了一个map,就是我们之前提到的key为文件名,value为id的map,通过这个map去得到id,有了id,就可以调用__webpack_require__

// r 函数
function webpackContext(req) {
	var id = webpackContextResolve(req);
	return __webpack_require__(id);
}

有点绕,仔细思考下就明白了。在webpack官方文档中,这种动态导入的模块,称为context module,即打包期间保留了模块的状态(上下文),在使用的时候再去确定。

显然他有一个缺点就是会把某个目录下(可以递归)所有符合规则的模块都预先打包准备好,因为打包期间无法确定最终到底需要使用哪个。

更深的了解,详见官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值