file-loader的踩坑
踩坑一:当我配置好file-loader之后运行npm run build,构建完成之后打开index.html,发现图片显示不出来,然后dist文件夹中还会多出一个显示不了的图片
html代码 .bg-image { background-image: url("../img/jx.png"); }
原因:当你对资源进行打包,因为你配置了file-loader所以会有对应的file-loader来帮你处理,但是webpack5里面又会默认帮你使用asset 模块进行处理,所以原因就是他们两个就冲突了
解决方案:
当在 webpack 5 中使用旧的 assets loader(如 file-loader
/url-loader
/raw-loader
等)和 asset 模块(即使你没有配置)时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 'javascript/auto'
来解决。 来自官方文档 webpack 中文文档 (docschina.org)
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'file-loader',
}
],
type: 'javascript/auto'
}
踩坑二:就算上面的配置完成之后,打包后的图片依旧显示不了,而且对资源的引用后面的路径变成了 /[object%20Module]
原因:
file-loader新版本默认使用了esModule语法,造成了引用图片文件时的方式和以前的版本不一样,而我们css-loader对url的处理又是将其转换成require()语句(commonjs语法)
注:css-loader会默认帮你转换url -> url(image.png) => require('./image.png') 官网的解释 webpack 中文文档 (docschina.org)
下面是css通过css-loader打包后的伪代码
const img=require('./image.png') module.exports=` div{ background:url('${img}') } ` ------------------------------------------------------------------- 经过webpack打包后的资源 通过cjs'引入' esm'导出'的代码如下
{ _esModule:true, default:123 } 由于webpack打包后的esModule导出代码会变成一个对象,里面有一个default属性,default属性才是你真正导出的东西
解决:
1.
//在require后面加上.default const imgEl = new Image(); imgEl.src = require('../img/dsj.png').default
2.
{ test: /\.(png|jpe?g|gif|svg)$/, use: [ { loader: 'file-loader', options: { //不使用esModule的语法导出 esModule: false }, } ], type: 'javascript/auto' }
推荐使用第二种