如何解决Webpack中SCSS引用图片显示错误及File Loader问题
解决Webpack 5中SCSS引用背景图显示错误的问题
问题说明
使用webpack@5.76.2在SCSS文件中设置图片作为背景图时,出现以下错误:
"图片“{PATH}”无法显示,因为它包含错误。"
已确认所有文件权限正常,通过file://协议可直接在浏览器中打开图片资源。
目录结构
- /assets/index.js
- /assets/webpack.config.js
- /assets/src/images/derp.png
- /assets/src/scss/
- /assets/src/scss/index.scss
- /assets/dist/images/
代码示例
index.js
import './scss/index.scss';
index.scss
.derp { background-image:url('../images/derp.png'); background-repeat:no-repeat; background-position:center; background-color:red !important; }
编译后异常
Webpack编译生成的CSS代码:
.derp { background-image: url(6a21cd8ac5284da706ed.png); background-repeat: no-repeat; background-position: center; background-color: red !important; }
浏览器中查看元素时,图片请求路径为assets/dist/6a21cd8ac5284da706ed.png,访问该路径时提示:
The image “https://derp.com/assets/dist/6a21cd8ac5284da706ed.png” cannot be displayed because it contains errors.
当前Webpack配置
const webpack = require('webpack'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry: { main: './src/index.js' }, mode: 'development', output: { filename: '[name].compiled.js', path: __dirname + '/dist' }, resolve: { symlinks: true, }, module: { rules: [ // Styles { test: /\.(sa|sc|c)ss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true }, }, { loader: 'resolve-url-loader', options: { sourceMap: true }, }, { loader: 'sass-loader', options: { sourceMap: true }, }, ], }, { test: /font-awesome\.config\.js/, use: [ { loader: 'style-loader' }, { loader: 'font-awesome-loader' } ] }, // Fonts > Load font files and save them in a 'fonts' directory. { test: /\.(ttf|eot|woff|woff2|otf)$/, exclude: /fontawesome-webfont\.(ttf|eot|woff|woff2)$/, use: { loader: 'file-loader', options: { name: 'fonts/[name].[ext]', }, }, }, // Images > Load image files and save them in an 'img' directory. { test: /\.(png|jpe?g|gif|svg)$/, use: { // loader: 'url-loader', // have tried this, too loader: 'file-loader', options: { //limit: 8192, // inline images up to 8KB name: 'images/[name].[ext]', }, }, }, ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].compiled.css', chunkFilename: '[id].css', }), ], };
解决方案
1. 切换到Webpack 5原生Asset模块(推荐)
Webpack 5已内置资源处理能力,file-loader已被标记为废弃,建议使用asset/resource替代:
// 替换原图片处理规则 { test: /\.(png|jpe?g|gif|svg)$/, type: 'asset/resource', generator: { filename: 'images/[name].[hash][ext]', publicPath: './' // 确保CSS中引用路径相对于CSS文件所在目录 } }
2. 修正file-loader与MiniCssExtractPlugin的路径配置
若继续使用file-loader,需补充publicPath配置,并为MiniCssExtractPlugin设置资源基础路径:
// 修改MiniCssExtractPlugin配置 new MiniCssExtractPlugin({ filename: '[name].compiled.css', chunkFilename: '[id].css', publicPath: './' // 指定CSS中资源的基础路径 }) // 修改file-loader规则 { test: /\.(png|jpe?g|gif|svg)$/, use: { loader: 'file-loader', options: { name: 'images/[name].[ext]', publicPath: './images/' // 确保生成的URL指向dist/images目录 }, }, }
3. 优化输出路径配置
确保output.path为绝对路径,可使用path.resolve避免拼接错误,同时设置全局资源基础路径:
const path = require('path'); // 需先引入path模块 output: { filename: '[name].compiled.js', path: path.resolve(__dirname, 'dist'), publicPath: './' }
4. 简化SCSS loader链
Webpack 5配合新版sass-loader时,resolve-url-loader可能并非必须,可尝试移除该loader,简化配置:
{ test: /\.(sa|sc|c)ss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true }, }, { loader: 'sass-loader', options: { sourceMap: true }, }, ], }
核心原因
编译后CSS生成的图片路径错误,导致浏览器请求的资源位置与实际输出的图片位置不匹配,或图片未被正确输出到指定目录。通过调整资源处理规则的路径配置,即可解决该问题。
内容的提问来源于stack exchange,提问作者Ryan Dorn
相关产品推荐
相关产品推荐

