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
,即打包期间保留了模块的状态(上下文),在使用的时候再去确定。
显然他有一个缺点就是会把某个目录下(可以递归)所有符合规则的模块都预先打包准备好,因为打包期间无法确定最终到底需要使用哪个。
更深的了解,详见官方文档
原文地址:https://blog.csdn.net/weixin_43459866/article/details/113188244
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。