You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack 5中图片导入绝对路径丢失/static/目录问题咨询

问题: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/前缀。

具体修改步骤

  1. 移除file-loader依赖
    卸载不再需要的file-loader:

    npm uninstall file-loader
    
  2. 替换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]'
      }
    }
    
  3. 统一资源输出路径(可选)
    若想统一所有资源的输出路径,可修改output.assetModuleFilename,无需在每个规则中重复设置:

    output: {
      path: assetsRoot,
      filename: getAssetsPath(`[name]${watch ? '' : '.[hash]'}.js`, 'js'),
      publicPath: assetsPublicPath,
      clean: true,
      assetModuleFilename: 'static/[name][ext]' // 统一设置资源路径前缀
    }
    

    此时上面的generator配置可简化为仅保留type: 'asset/resource'。

  4. 检查publicPath配置
    确认assetsPublicPath的值正确,例如资源根目录为/build/时,需设置为'/build/',确保生成的路径为/build/static/image.jpg,对应mysite.com/build/static/image.jpg。

内容的提问来源于stack exchange,提问作者football manager

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:40:33