Webpack报错无法解析根路径图片,求配置解决方案
问题描述
我有如下的_url.scss文件:
$host-name: 'https://my-dev-host.com'; $icon-arrow-up-down: $host-name + '/folder/img/upDownArrows.png';
Webpack可以正常编译该文件且运行完美。但作为Webpack新手,我不想为每个环境修改$host-name变量并重新编译文件,尝试改用根路径加载文件:
//$host-name: ''; --no more needed $icon-arrow-up-down: '/folder/img/upDownArrows.png';
但修改后Webpack编译器抛出错误:"Module not found: Error: Can't resolve '/folder/img/upDownArrows.png'"。我知道应该是缺少某些配置,但不确定具体项。另外,我不能将该.png文件放在项目内提供服务。我的webpack.common.js配置如下:
const path = require('path'); const webpack = require('webpack'); const package = require('./package.json'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const outputPath = path.join(__dirname, 'dist'); const isProduction = process.env.NODE_ENV === 'production '; module.exports = { entry: { app: path.resolve(__dirname, './src/app.js'), styleguide: path.resolve(__dirname, './src/styleguide/scripts.js'), backoffice: path.resolve(__dirname, './src/backoffice/scripts.js'), }, output: { path: outputPath, publicPath: '/dist/', }, plugins: [ new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: [`${outputPath}/*.hot-update.*`], dangerouslyAllowCleanPatternsOutsideProject: true, dry: false, }), new webpack.BannerPlugin({ banner: `[base] || Version: ${package.version} || Generated: ${new Date()}`, }), ], resolve: { fallback: { fs: false, } }, module: { rules: [ { test: /\.js?$/, exclude: /node_modules/, }, { test: /\.s?[ac]ss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 2, sourceMap: !isProduction, }, }, { loader: 'postcss-loader', options: { sourceMap: !isProduction, }, }, { loader: 'sass-loader', options: { sourceMap: !isProduction, }, }, ], }, { test: /\.(png|jpg|jpeg|svg|gif)$/, type: 'asset/resource', }, { test: /\.(woff|woff2|eot|ttf|otf)$/, type: 'asset/resource', }, ], }, stats: { errorDetails: true, }, };
解决方案
问题核心是:Webpack会将'/folder/img/upDownArrows.png'这类根路径视为项目内文件路径,尝试从项目根目录查找资源,而非当作外部URL处理。以下两种方案可解决:
方案1:让Webpack忽略根路径资源解析
修改css-loader配置,添加url.filter选项,跳过对根路径资源的解析:
{ loader: 'css-loader', options: { importLoaders: 2, sourceMap: !isProduction, url: { filter: (url) => { // 跳过以/开头的根路径,不进行文件解析 if (url.startsWith('/')) { return false; } return true; }, }, }, }
配置后,Webpack会直接保留CSS中的根路径,浏览器运行时会根据当前域名的根路径请求资源。
方案2:通过环境变量自动注入域名
如果需要不同环境自动切换域名,可通过sass-loader注入环境变量:
- 为不同环境设置环境变量,比如开发环境:
ASSET_HOST=https://my-dev-host.com,生产环境:ASSET_HOST=https://my-prod-host.com - 修改
sass-loader配置:
{ loader: 'sass-loader', options: { sourceMap: !isProduction, additionalData: `$host-name: '${process.env.ASSET_HOST}';`, }, }
之后在_url.scss中可继续使用变量拼接路径:
$icon-arrow-up-down: $host-name + '/folder/img/upDownArrows.png';
编译时会自动注入对应环境的域名,无需手动修改SCSS文件。
注意事项
- 方案1适合资源路径基于当前域名根目录的场景,需确保部署服务器的对应路径存在资源
- 方案2适合资源存放在独立CDN或不同环境域名不同的场景,通过环境变量实现灵活切换
内容的提问来源于stack exchange,提问作者Ricardo Saraiva
相关产品推荐
相关产品推荐

