require.context的白话版讲解
发布日期:2021-05-04 18:16:53 浏览次数:27 分类:技术文章

本文共 1227 字,大约阅读时间需要 4 分钟。

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,即打包期间保留了模块的状态(上下文),在使用的时候再去确定。

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

更深的了解,详见

上一篇:浏览器渲染原理中的那些事儿,前端开发必看
下一篇:npm publish failed to parse json EJSONPARSE

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2025年03月26日 14时22分34秒