关于webpack动态路径打包的问题

背景介绍

今天在 review 代码的时候看到这么一行代码:

1
2
3
// res为接口返回的数据
state.activityItem.bottomImg = require(`../../routes/xxx/components/xxx/images/xxx_${res.xxx}.png`);
// ...

原本以为 webpack 只能做“静态”资源的打包,这里的静态指的是文件是编译时就能够确定的,但这里文件的路径是要运行时,即接口返回时才能确定,在编译时 webpack 无法找到对应的资源,理应出错才对。

但实际编译后发现不仅编译没有出错,相应的文件也被正确打包出来了,颠覆了我对 webpack 引用机制的理解。

原理分析

经过多次测试后发现,webpack 其实是能够做到“动态引入”,也在官方文档查到了相关的资料:https://webpack.js.org/guides/dependency-management/#require-with-expression

require with expression
A context module is generated. It contains references to all modules in that directory that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids.

实际上上面的代码被 webpack 理解成了一句正则表达式,相当于/^../../routes/xxx/components/xxx/images/xxx_*.png$/,也就是匹配路径下所有已“xxx_”开头的 png 文件,只要满足这个正则的文件都会被打包出来。

总结

虽然 webpack 支持动态引入的方式,但依旧不建议开发中大范围使用这项特性。从 es 发展的趋势来看,到 es6 的模块引入已经只支持静态引入的方式了。

因为动态引入的方式虽然方便,却存在一些无法优化的问题,例如在模块中会无法 tree-shaking,在项目中使用的话,会让依赖关系变得不清晰。

如果正则写的比较宽泛,比如@/routes/.*,会将目录下的所有文件都打包一遍,大大降低的打包的速度,还可能会让打包后的文件出现很多“不需要”的资源,如果目录下出现 webpack 无法解析的文件(没有配置 loader 或路径错误),打包时会直接报错。

一定要使用这项特性的话,一定要将文件路径限制到最接近的层级,并加上特定的后缀使用。


关于webpack动态路径打包的问题
https://www.wobushi.top/2021/关于webpack动态路径打包的问题/
作者
Pride Su
发布于
2021年3月30日
许可协议