Webpack 5中图片导入绝对路径丢失/static/目录问题咨询
迁移至Webpack 5并完成所有依赖库更新后,启动本地环境发现图片及Font Awesome图标无法显示。查看浏览器控制台发现,图片路径从mysite.com/build/static/image.jpg被修改为mysite.com/build/image.jpg,手动修正路径后图片可正常显示。请问为何路径会丢失/static/部分?
以下是Webpack配置代码:
const path = require('path'); const glob = require('glob'); const {ProvidePlugin} = require('webpack'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); const WebpackNotifierPlugin = require('webpack-notifier'); const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); const Dotenv = require('dotenv-webpack'); const { WebpackManifestPlugin } = require('webpack-manifest-plugin'); const {watch, assetsRoot, assetsPublicPath, assetsSubDirectory} = require('./config'); const getAssetsPath = (_path, dir) => { return path.posix.join(dir ? dir : assetsSubDirectory, _path); }; const getPlugins = () => { if (watch) { return [ new BrowserSyncPlugin({ proxy: 'https://mysite/', host: 'mysite.com', port: '3000', open: 'external', }), ]; } return [ // Extract CSS into its own file new MiniCssExtractPlugin({ filename: getAssetsPath('[name].[hash].css', 'css'), }), ]; }; module.exports = { mode: watch ? 'development' : 'production', devtool: watch ? 'inline-source-map' : 'source-map', watch, entry: { app: [ ...glob.sync('./assets/js/**/*.js'), './assets/sass/app.scss', ...glob.sync('./assets/css/**/*.css'), ], react: './react/index.js', }, output: { path: assetsRoot, filename: getAssetsPath(`[name]${watch ? '' : '.[hash]'}.js`, 'js'), publicPath: assetsPublicPath, clean: true, assetModuleFilename: '[name][ext]' }, resolve: { extensions: ['.js', '.jsx', 'css', 'scss'], modules: [path.join(__dirname, '..', 'node_modules'), 'node_modules'], }, optimization: { minimizer: [new CssMinimizerPlugin()], }, plugins: [ ...getPlugins(), new ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', }), new WebpackNotifierPlugin(), new WebpackManifestPlugin(), new CssMinimizerPlugin(), new Dotenv(), ], module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, { test: /\.s?css$/, use: [ { loader: watch ? 'style-loader' : MiniCssExtractPlugin.loader, }, { loader: 'css-loader', options: { sourceMap: true, importLoaders: 2, }, }, 'scoped-css-loader', 'sass-loader', ] }, { test: /\.svg?$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'static/', } } ], }, { test: /\.(png|jpe?g|gif)(\?.*)?$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'static/', } } ], }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'static/', } } ], }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'static/', }, }, ], }, ], } };
解决方法
核心原因
Webpack 5已内置Asset Modules,完全替代了file-loader、url-loader等第三方工具。你当前仍在使用file-loader,同时output.assetModuleFilename: '[name][ext]'的配置会覆盖file-loader的outputPath设置,导致资源路径丢失static/前缀。
具体修改步骤
移除file-loader依赖
卸载不再需要的file-loader:npm uninstall file-loader替换file-loader为Asset Modules
修改module.rules中所有资源处理规则,用Webpack 5原生Asset Modules替代:// 替换原有的file-loader规则 { test: /\.svg$/, type: 'asset/resource', generator: { filename: 'static/[name][ext]' } }, { test: /\.(png|jpe?g|gif)(\?.*)?$/, type: 'asset/resource', generator: { filename: 'static/[name][ext]' } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, type: 'asset/resource', generator: { filename: 'static/[name][ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, type: 'asset/resource', generator: { filename: 'static/[name][ext]' } }统一资源输出路径(可选)
若想统一所有资源的输出路径,可修改output.assetModuleFilename,无需在每个规则中重复设置:output: { path: assetsRoot, filename: getAssetsPath(`[name]${watch ? '' : '.[hash]'}.js`, 'js'), publicPath: assetsPublicPath, clean: true, assetModuleFilename: 'static/[name][ext]' // 统一设置资源路径前缀 }此时上面的generator配置可简化为仅保留
type: 'asset/resource'。检查publicPath配置
确认assetsPublicPath的值正确,例如资源根目录为/build/时,需设置为'/build/',确保生成的路径为/build/static/image.jpg,对应mysite.com/build/static/image.jpg。
内容的提问来源于stack exchange,提问作者football manager

