htmlwebpackwebpack-file-loaderwebpack-html-loaderwebpack-bundle

Html-loader + file-loader not bundling the correct image source


I'm planning to use Webpack for a project and I'm setting up my workflow with Html-loader + file-loader to get a production html file with dynamic src for the images, as Colt Steele teaches in this video. Here are my src/ files:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Popular on Letterboxd</title>
</head>
<body>
  <img src="./assets/chira.jpg" />
</body>
</html>

index.js:

import img from './assets/chira.jpg';
import "./main.css";

And main.css

body {
  background-color: darkblue;
}

These are my config files (I have an individual for dev and production and a common for both):

webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',

  devtool: "none",
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ],
      },
      {
        test: /\.html$/,
        use: ["html-loader"]
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[hash].[ext]',
              publicPath: 'assets',
              outputPath: 'assets/img'
            }
          }
        ]
      }
    ],
  },
};

webpack.dev.js:

const path = require('path');
const common = require("./webpack.common");
const merge = require('webpack-merge');

module.exports = merge(common, {
  mode: "development",
  devServer: {
    contentBase: path.join(__dirname, 'src'),
  },
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "dist")
  },
});

And webpack.prod.js:

const path = require('path');
const common = require("./webpack.common");
const merge = require('webpack-merge');


module.exports = merge(common, {
  mode: "production",
  output: {
    filename: "main.[contentHash].js",
    path: path.resolve(__dirname, "dist")
  },
});

However, when I run npm run build, which executes this command:

"build": "webpack --config webpack.prod.js"

And I get the expected dist folder with assets/img/[name].[hash].[ext], but in my index.html I do not get the expected src tag:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Popular on Letterboxd</title>
</head>
<body>
  <img src="[object Module]" />
<script type="text/javascript" src="main.e55bd4ff82bf2f5cec90.js"></script></body>
</html>

I've been trying to fix the problem for a while now, but I can't seem to get a proper answer anywhere, and nothing that I've tried have worked so far. I would appreciate if anyone who has encountered this problem can address how they fixed it, or if someone has any clue of what the problem might be and what can I do. Thanks in advance!


Solution

  • If file-loader verions is 5.0 then. Adding another option on file-loader as "esModule: false" will solve this problem.

    {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[hash].[ext]',
              publicPath: 'assets',
              outputPath: 'assets/img',
              esModule: false
            }
          }
        ]
      }