Webpack使用css-loader与file-loader正确解析CSS中url路径的问题
解决方案
问题根源
你遇到的问题本质是模块导出规范不匹配+Webpack资源处理规则重复:
css-loader默认使用ES模块导出资源路径,而你给图片配置的file-loader关闭了ES模块使用CommonJS导出,两边规范不一致导致CSS拿到的是模块导出代码而非直接的路径- 如果你使用的是Webpack 5,内置的Asset Modules默认会处理图片资源,和你手动配置的
file-loader重复处理同一份资源,就会生成多余的模块文本文件
方案1:推荐使用Webpack 5内置Asset Modules(无需file-loader)
Webpack 5已经内置了静态资源处理能力,不需要额外安装file-loader,直接替换原来的图片、SVG处理规则即可解决冲突,同时支持JS导入和CSS url()引用:
module.exports = { optimization: { splitChunks: { chunks: 'all' } }, module: { rules: [ { test: /\.(m|c)?jsx?$/i, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, }, { test: /\.css$/i, use: [ 'style-loader', 'css-loader' ] }, // 替换原来的png/jpg/gif、svg两条file-loader规则 { test: /\.(png|jpe?g|gif|svg)$/i, type: 'asset/resource', generator: { // 可自定义输出的文件名格式,和原来file-loader效果一致 filename: '[contenthash][ext][query]' } }, { test: /\.pug$/i, use: { loader: 'pug-loader', options: { pretty: true } } } ], } }
方案2:必须保留file-loader的修改方法
如果你的项目是Webpack 4版本,或者必须保留file-loader使用,做三处修改即可:
- 给
css-loader添加配置,关闭ES模块导出,和file-loader的CommonJS规范对齐,同时设置importLoaders保证资源正确传递给后续loader - 给SVG的
file-loader配置也加上esModule: false,和图片规则保持一致 - Webpack 5用户额外添加禁用内置Asset的配置,避免重复处理
修改后的完整配置:
module.exports = { // Webpack 5用户额外添加这一行,禁用内置资源处理 experiments: { asset: false }, optimization: { splitChunks: { chunks: 'all' } }, module: { rules: [ { test: /\.(m|c)?jsx?$/i, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, }, { test: /\.css$/i, use: [ 'style-loader', { loader: 'css-loader', options: { esModule: false, importLoaders: 1 } } ] }, { test: /\.(png|jpe?g|gif)$/i, use: { loader: 'file-loader', options: { esModule: false } } }, { test: /\.svg$/i, use: { loader: 'file-loader', // 给svg也加上esModule关闭配置 options: { esModule: false } } }, { test: /\.pug$/i, use: { loader: 'pug-loader', options: { pretty: true } } } ], } }
两种方案修改后重新打包,就不会生成多余的模块文件,CSS的url()会直接指向正确的图片路径,同时JS中导入图片的功能也能正常使用。
内容的提问来源于stack exchange,提问作者user3808059
相关产品推荐
相关产品推荐

