clean-webpack-plugin icon indicating copy to clipboard operation
clean-webpack-plugin copied to clipboard

Unexpected removal of `background-image` files

Open aaaatpdev opened this issue 5 years ago • 15 comments

Steps to reproduce

  1. cd /path/to/project

  2. npm init -y

  3. npm install -D webpack webpack-cli style-loader css-loader mini-css-extract-plugin file-loader clean-webpack-plugin

  4. Code to reproduce

package.json scripts:

    "build": "webpack --mode production",
    "dev": "webpack --mode development --watch",

webpack.config.js:

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

var config = {
  entry: {
    main: './src/main.js',
  },
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'build/app.js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/,
        loader: 'file-loader',
        options: {
          outputPath: 'build/images',
          name: '[name].[hash:7].[ext]',
        },
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'build/app.css',
    }),
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: [ 'build/**/*', ],
    }),
  ],
}

module.exports = config

src/assets/images/bg.png: any dummy image (e.g. https://dummyimage.com/600x400/000/fff).

src/css/app.css:

.whatever {
  background-image: url('../assets/images/bg.png');
}

src/main.js:

import './css/app.css'
  1. npm run dev

  2. Save src/css/app.css

Observed behavior

bg.png unexpectedly disappears (from public/build/images).

aaaatpdev avatar Aug 23 '19 05:08 aaaatpdev

Same problem here, all images are deleted and never recreated. It happens only in watch mode. As soon as a file is modified, the plugin does refresh css and js, but erases images.

kaligrafy avatar Sep 10 '19 10:09 kaligrafy

You either need to set cleanStaleWebpackAssets: false or add negative patterns to cleanAfterEveryBuildPatterns: ['!*.png'].

chrisblossom avatar Sep 10 '19 15:09 chrisblossom

@chrisblossom, those are possible workarounds. Is there any problem to keep background-image files alive?

aaaatpdev avatar Sep 23 '19 04:09 aaaatpdev

@aaaatpdev Please clarify what you are asking. Are you asking if it is an issue to keep stale assets on disk? If so, that is completely up to you.

chrisblossom avatar Sep 24 '19 18:09 chrisblossom

I'm experiencing this issue as well:

When I do a regular "production" build, All my files get copied over correctly. However, on "watch" builds, the files get copied over on the initial build, but on any change, all the files copied over by copy-webbpack-plugin get deleted (and are not copied over again).

Probably related to webpack-contrib/copy-webpack-plugin#385, webpack-contrib/copy-webpack-plugin#261 and statianzo/webpack-livereload-plugin#53

marekdedic avatar Sep 28 '19 20:09 marekdedic

@chrisblossom, i mean that the described behavior is unexpected (background-image files aren't stale assets) and should be fixed. Or maybe i'm missing something?

aaaatpdev avatar Sep 30 '19 03:09 aaaatpdev

I have the same issue with fonts that are extracted via the minicss-extract-plugin.

jvandesande avatar Oct 02 '19 09:10 jvandesande

I have the same issue. ~~I think that it can be avoided if the ignore pattern can be set.~~

I was able to work around it by setting cleanAfterEveryBuildPatterns.

mya-ake avatar Dec 10 '19 09:12 mya-ake

You can use remove-files-webpack-plugin for this.

If i'm get it right: in watch mode need to delete all except files which in public/build/images folder. Here is solution with that plugin.

Config:

plugins: [
  new RemovePlugin({
    // in watch mode (only in "watch" mode, not "normal" mode!) 
    // remove all files, folders and subfolders from `./public` except 
    // `./public/build/images` folder (and files which included in that folder).
    watch: {
      root: './public',
      test: [
        {
          folder: '.',
          method: () => true,
          recursive: true
        }
      ],
      exclude: [
        './build/images'
      ]
    }
  })
]

Note: i'm the creator of this plugin, so, it's a bit of an advertisement.

Amaimersion avatar Feb 26 '20 21:02 Amaimersion

I have the same issue. ~I think that it can be avoided if the ignore pattern can be set.~

I was able to work around it by setting cleanAfterEveryBuildPatterns.

@mya-ake Could you clarify your workaround?

Xerrion avatar May 28 '20 09:05 Xerrion

You can use remove-files-webpack-plugin for this.

If i'm get it right: in watch mode need to delete all except files which in public/build/images folder. Here is solution with that plugin.

Config:

plugins: [
  new RemovePlugin({
    // in watch mode (only in "watch" mode, not "normal" mode!) 
    // remove all files, folders and subfolders from `./public` except 
    // `./public/build/images` folder (and files which included in that folder).
    watch: {
      root: './public',
      test: [
        {
          folder: '.',
          method: () => true,
          recursive: true
        }
      ],
      exclude: [
        './build/images'
      ]
    }
  })
]

Note: i'm the creator of this plugin, so, it's a bit of an advertisement.

I tried to use your plugin, but bump into the same problem. I.e. adding a folder to the exclude array still insists on removing the folder's contents. Props for the efforts though.

Edit: I managed to get desired result still by restructuring my build folder a bit and setting recursive to false.

stock-dd avatar Aug 07 '20 08:08 stock-dd

I think I've been having the same issue, although mine was with sw.js. Running this plugin would continually remove the sw.js file from the build folder.

Stepping through the plugin, my file was being removed as part of handleInitial, and using the cleanOnceBeforeBuildPatterns of ['**/*'] (which is the default value if this property isn't provided in the config object).

For my scenario, I've just set cleanOnceBeforeBuildPatterns to [] in my config object, and now my sw.js file isn't being deleted.

luke-denton-aligent avatar Sep 10 '20 04:09 luke-denton-aligent

I've also got this issue, it either doesn't clean anything anymore or it randomly cleans everything that the copy plugin provided (for example the .htaccess to rewrite to index.html) and it's random. It suddenly decides to do so.

We've got the following config which means it shouldn't do it. But still sometimes randomly it decides to clean all the files provided by the copy plugin

		new CleanWebpackPlugin({
			cleanAfterEveryBuildPatterns: [],
			cleanStaleWebpackAssets: false,
			verbose: true,
			dry: false,
		}),

we're on version 3.0.0. Webpack 4, upgrading to 5 to see if that helps

SamanthaAdrichem avatar Nov 06 '20 10:11 SamanthaAdrichem

Honestly, my solution was to go to gulp for this kind of stuff and use gulp-webpack. In my (albeit limited) experience, webpack as a "task runner" just isn't that great. So for these kinds of tasks (copying config files etc.) I use gulp and when I want a bundler, I call webpack with gulp-webpack.

Ofc, this is just a personal preference, ymmv...

marekdedic avatar Nov 06 '20 13:11 marekdedic

I can confirm @luke-denton-aligent findings where cleanOnceBeforeBuildPatterns sometimes (typically after some errors occurred in previous builds and were now fixed) removes (almost?) everything at weird times (after whole bunch of successful rebuilds in watch mode). I'm having trouble isolating the issue and can't invest more time into it right now, however cleanOnceBeforeBuildPatterns: [] did fix it in our case.

Kukkimonsuta avatar Dec 23 '20 20:12 Kukkimonsuta