file-loader的踩坑


踩坑一:当我配置好file-loader之后运行npm run build,构建完成之后打开index.html,发现图片显示不出来,然后dist文件夹中还会多出一个显示不了的图片

html代码

.bg-image {
  background-image: url("../img/jx.png");
}

原因:

css-loader会默认帮你转换url -> url(image.png) => require('./image.png') 官网的解释 webpack 中文文档 (docschina.org)

然后会有对应的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语法)

解决:

 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'
 }    

推荐使用第二种