webpack file-loader duplicates files
Asked Answered
L

3

11

I'm using webpack and it's file-loader + html-loader to emit files into my output directory. It works almost as expected, because it also duplicates those files.

Here is a part of my webpack.config.js file:

module.exports = {
   module: {
      rules: [
         { test: /\.html$/, use: ["html-loader"] },
         {
            test: /\.(jpg|png)$/,
            use: {
               loader: "file-loader",
               options: {
                  name: "[name].[ext]",
                  outputPath: "img",
               },
            },
         },
      ],
   },
};

There is a small example of how my output directory looks like:

dist/
- img/
   - img1.png
   - img2.png
- ab0d12.png
- c3d612.png
- index.html
- bundle.js

The two images with hashed names are unwanted duplicates of those in img/ directory. As you can see in the example above, I'm not even setting the name to be hashed and I also cannot open the duplicate files in any way.

I'm using some plugins like HtmlWebpackPlugin or CleanWebpackPlugin, but I believe they are not causing the problem.

Versions:

  • webpack 5.28.0
  • file-loader 6.2.0
  • html-loader 2.1.2
Louvar answered 1/4, 2021 at 15:20 Comment(2)
Can you show the .html or .js file where you're importing those images? Where are img1.png and img2.png stored before bundling?Califate
@Califate images are stored inside a img/ dir inside the src/ dir. I'm importing them using src attribute: <img src="./img/img1.png">.Encaenia
L
14

After a long searching I came across this SO question that seemed very similar to mine, however, the cause of the file duplication were different.

In version 5, webpack introduced Asset Modules as a replacement for raw-loader, url-loader and file-loader and which are now ran by default:

Asset Modules is a type of module that allows one to use asset files (fonts, icons, etc) without configuring additional loaders.

Every time webpack started bundeling my project, asset/resource and file-loader were running at the same time and resulted into duplication.

Eventually, all I had to do to fix my problem was to remove the file-loader from the webpack.config.js file and set a output.assetModuleFilename to my desire output directory.

Louvar answered 2/4, 2021 at 14:41 Comment(4)
I was going to ask the same question. Then I found yours. Thanks!Gavotte
yes that's the right answer i faced the same issue thanks BroMosira
Thats's it. Thank you!Collyrium
can you add ur webpack config for better understanding? I am confused.John
C
0

webpack.prod.js (dev config does not need compress image)

...
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        filename: 'assets/app.js',
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        assetModuleFilename: 'img/[name][ext][query]' // dont use [hash] in name
    },
    module: {
        rules: [
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                type: "asset/resource"
            }
        ],
    },
    plugins: [
        new ImageMinimizerPlugin({
            minimizerOptions: {
                plugins: [
                    ["mozjpeg", { quality: 60 }],
                    ["pngquant", { quality: [0.6, 0.8] }],
                ],
            },
        })
    ]
};

webpack5 use Asset Modules type replaces all of these loaders, and with image-minimizer-webpack-plugin to compress images

Coopery answered 25/8, 2021 at 3:12 Comment(2)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.Godewyn
Config sample added @Mousam SinghCoopery
F
0

Like @Daweed already explained, the files are processed twice: Once by the file-loader and once by the asset module.

If for some reason you are not ready to migrate to asset modules, you can disable the asset module processing by adding

type: 'javascript/auto'

to the file-loader as mentioned in the documentation:

[...] you might want to stop Asset Module from processing your assets again as that would result in asset duplication. This can be done by setting asset's module type to 'javascript/auto'.

Fireman answered 12/5, 2023 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.