html-loader is not getting correct img src path

Finally I found the solution.

I guess the error is caused by the problem which is mentioned by @Daweed in the top comment.

I am using webpack 5 but didn't notice that file-loader/url-loader/raw-loader is deprecated now.

The solution is to uninstall file-loader/url-loader/raw-loader from dev-dependency(and remember also remove all related config setting.),and follow the guides here.

my config setting now(which solved all problems) is below:

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: {
    main: ['./src/index.js', './src/scss/main.scss'],
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].min.js',
    path: resolve(__dirname, 'build'),

  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
          }
        ],
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(jpe?g|png|gif)$/,
        type: 'asset/resource',
        generator: {
          filename: 'img/[hash][ext]'
        }
      }


    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './index.html'
    })
  ]
}

Looks there is a conflict between file-loader and html-loader plugins, thus it's generating corrupted assets.

However, html-loader will take care of loading all the images (supported sources), we don't need additional plugin file-loader to have that support.

So you can try just by removing file-loader configuration

  {
    test: /\.(jpg|png|gif)$/,
    use: [
      {
        loader: 'file-loader',
        options: {
          name: '[name].[ext]',
          outputPath: '/img/',
          pubicPath: '/img/'
        }
      }
    ],
  }