David Malášek
David Malášek

Reputation: 1432

webpack file-loader duplicates files

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:

Upvotes: 11

Views: 3898

Answers (3)

Niklas Dada
Niklas Dada

Reputation: 401

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'.

Upvotes: 0

LinTao
LinTao

Reputation: 48

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

Upvotes: 0

David Malášek
David Malášek

Reputation: 1432

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.

Upvotes: 14

Related Questions