共计 2059 个字符,预计需要花费 6 分钟才能阅读完成。
起因
为什么会突然用到 webpack 这个管理特性呢?
项目某个页面需要引入 N 张 demo 图片。即资源的批量引入:如果要引入 10+ 个以上的图片资源,就需要写 10+ 个如下的引入代码:import XXX from ‘relative/path/assets/imgs/xxx’;,那如果再多一点的静态资源需要引入呢?这时候 require.context 就派上了用场。
文档
官方文档的介绍先放在这里,可小觑一下,了解使用姿势。
栗子????_???? 来一个
话不多说,针对上面的场景,我们上一下代码吧。
场景需要我们引入某个指定文件夹下的所有 webp 格式的图片,在单击 demo1 的时候展示 demo1 下的 x 张案例图,在单击 demoX 的时候展示 demoX 下的 x 张案例图。
// 通过 require.context 的方式引入指定的路径下匹配到的模块引用
const demoImgsContext = require.context(‘@src/assets/imgs/demo’, false, /\.webp$/);
…
// 使用姿势
trigger(type) {
this.demoImgs = Arry.from({length: config.type}, (key, value) => value + 1)
.map(index => demoImgsContext(`./${type}_demo${index}.webp`));
}
举一反三的场景还有需要的么?比如 vuex 引入多个 module 的 store。也可以使用这个方法。
// 添加 module 文件是,文件命请按照 module_XXX 的方式命名
// 自动引入 module 文件夹下的 js 文件
const mutationContext = require.context(‘./module’, false, /.*\.js/);
const modules = mutationContext.keys().reduce((prev, cur) => {
// 排除 module_root 文件
const matches = cur.match(/module_(?!.*root)(\w+)\.js/);
const key = matches && matches[1];
key && (prev[key] = mutationContext(cur).default);
return prev;
}, {});
接下来,让我们看一下,require.context 是如何做到动态引入资源的呢?
看下打包后的 dist 目录下,我们的静态图片案例 chunk 这个部分的代码是啥样的。
trigger 方法中引用模块资源的代码如下,对 y 方法进行调用,传入了一个资源的路径。
map(function (e) {
return y(“./”.concat(t, “_demo”).concat(e, “.webp”))
})
那 y 方法是什么呢?顺藤摸瓜,继续看下打包后的代码。
y = a(“ae36”);
y 方法是某个模块的 export,继续查看这个 id 下的模块代码:
ae36: function (t, e, a) {
// 此处是一个 map 映射,key 值和真正的资源 id 的映射
var i = {
“./a_module_demo1.webp”: “6085”,
“./a_module_demo2.webp”: “fd3b”,
“./b_module_demo1.webp”: “cbf6”,
“./b_module_demo2.webp”: “220e”,
“./c_module_demo1.webp”: “273e”,
“./c_module_demo2.webp”: “5a5e”,
“./d_module_demo1.webp”: “75b0”,
“./d_module_demo2.webp”: “2d3e”
};
// 此处根据 module 的 id 值,真正 require 一个资源
function r(t) {
var e = o(t);
return a(e)
}
function o(t) {
var e = i[t];
if (!(e + 1)) {
var a = new Error(“Cannot find module ‘” + t + “‘”);
throw a.code = “MODULE_NOT_FOUND”, a
}
return e
}
r.keys = function () {
return Object.keys(i)
}, r.resolve = o, t.exports = r, r.id = “ae36”
},
“6085”,”fd3b” 等 map 映射的 value 值可想而知,是真正的资源 id 值,其对应的模块映射如下:
6085: function (t, e) {
t.exports =
“//${你配置的项目 publicPath}/img/1_module_demo1.ed6db768.webp”
},
当用户触发 trigger 方法时,根据 type 和 index 指定的值,require.context 存储的模块资源引用会根据 key 值找到真正的资源模块,进行 require,浏览器会帮助我们下载相应的资源,做到了批量引入后按需加载的想法。
手痒的同学可以磨刀霍霍试试了~