Webpack 5 images not found when importing to a module

Viewed 1578

I have a very simple Webpack 5 config, and I am trying to import images for use in my React app. I am able to import the image and use it without Webpack complaining:

import SomeImage from 'assets/some-image-jpg'
...
<img src={SomeImage} />

However, the image is not found in the browser. I am using webpack-manifest-plugin and the devServer option writeToDisk to serve the assets via Django. The JS and CSS work as expected.

const path = require('path');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: './front/index.js',
  output: {
    filename: 'index-bundle.js',
    path: path.resolve(__dirname, './local-static'),
    publicPath: '/',
    assetModuleFilename: 'img/[hash][ext][query]',
  },
  devServer: {
    writeToDisk: true,
    disableHostCheck: true,
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: "babel-loader",
      },
      {
        test: /\.(scss|css)$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
      },
    ]
  },
  resolve: {
    modules: [
      path.join(__dirname, "front"),
      "node_modules"
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ filename: 'css/[name].css' }),
    new WebpackManifestPlugin({ publicPath: './' }),
  ],
};

EDIT: Sample output of mainfest.json file:

{
  "main.css": "./css/main.css",
  "main.js": "./index-bundle.js",
  "main.jpg": "./img/fbf8476a272a27c10e80.jpg",
  "front/assets/no-image.jpg": "./img/fbf8476a272a27c10e80.jpg"
}

"front" is the name of the folder where the source files are stored.

EDIT 2: Contents of output folder:

├── css
│   └── main.css
├── img
│   └── fbf8476a272a27c10e80.jpg
├── index-bundle.js
└── manifest.json
1 Answers

Your image appears to exist, only it has been renamed with the with a hash key prefix. This is to get around image cache issues when the file name doesn't change, but the image has. Normally the plugin is smart enough to fix most but NOT all of the references to the rename.

To check whether your image file is actually being written to disk you can temporarily alter the assetModuleFilename key to use the original name and file extension as shown in the section below. If your image file is unlikely to change you can probably make this change permanent. You should now hopefully see the file in the browser!

Otherwise workaround by manually replacing the new hashed name of the image referenced in your config or other files where necessary. A map file manifest.json of all hash entries can be generated by the plugin automatically

example:

  output: {
    publicPath:"", // default is "auto"
    path: path.join(__dirname, "build"),
    filename: "[name].bundle.js",
    clean: true,
    assetModuleFilename: '[name][ext]'
  },

Warning! Do not put a period mark(.) between the substitutions in the assetModuleFilename key as is done in the filename key or you may get a file not found error.

Related