很久之前就遇到过这个问题,一直在造轮子,难免会遇到一些库需要放图片作为背景图,上次是作为内联base64解决这个问题,但是也没有追寻为什么。这次又遇到了这个问题,应该仔仔细细弄个清楚,并花时间整理记录一下。
这次是打包上篇文章的3d-earth 组件,threejs 需要一些纹理地图,为了简单引用就不让外部传入纹理图片,所以需要包内纹理打包图片。
在 webpack 5 之前,通常使用:
raw-loader 将文件导入为字符串 url-loader 将文件作为 data URI 内联到 bundle 中 file-loader 将文件发送到输出目录 资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
使用 url-loader,并且配置资源体积限制实现。 当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 ‘javascript/auto’ 来解决。
{
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
type: "asset"
},
现在,webpack 将按照默认条件,自动地在 resource 和 inline 之间进行选择:小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型。
打包完之后的组件包:
可以看出有图片已经打包成resource 处理了,如果将打包后的js直接放到Html 中引用也是没有问题的,路径也正确。
file://
本地连接问:为什么会是本地路径呢?
带着这个问题,一起看一个打包之后的代码
先看这一段:
/***/ "./src/img/earth_glow.png":
/*!********************************!*\
!*** ./src/img/earth_glow.png ***!
\********************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval("module.exports = __webpack_require__.p + \"9e4abf8518ca87b87326.png\";\n\n//# sourceURL=webpack://3d-earth/./src/img/earth_glow.png?");
/***/ }),
不难看出最终图片输出的路径是:webpack_require.p + 图片名 问:webpack_require.p 是什么路径呢?
__webpack_require是webpack 打包的核心函数,webpack_require.p一般是从 output.publicPath 读取的。
可以参考官网了解详情 :传送门
重点看下常用几种类型:
output: {
// One of the below
publicPath: 'auto', // It automatically determines the public path from either `import.meta.url`, `document.currentScript`, `<script />` or `self.location`.
publicPath: 'https://cdn.example.com/assets/', // CDN(总是 HTTPS 协议)
publicPath: '//cdn.example.com/assets/', // CDN(协议相同)
publicPath: '/assets/', // 相对于服务(server-relative)
publicPath: 'assets/', // 相对于 HTML 页面
publicPath: '../assets/', // 相对于 HTML 页面
publicPath: '', // 相对于 HTML 页面(目录相同)
},
如果什么不设置的时候也就auto
,这时候默认路径是 import.meta.url
import.meta是一个给JavaScript模块暴露特定上下文的元数据属性的对象。它包含了这个模块的信息,比如说这个模块的URL。
不难看出,我没有设置output.publicPath,所以默认是auto
也就是import.meta.url 所以最后图片是一个本地file
路径
问题分析出了原因,那么如果以后我们想在第三方包里加图片应该怎么办呢?
我最后归纳出了几种办法,如果有更好的欢迎留言:
asset/inline
,这样打包内联成base64,就不会有路径问题了我一直觉得有更好的解决办法,欢迎留言区大佬赐教