johnagan / clean-webpack-plugin

A webpack plugin to remove your build folder(s) before building
MIT License
1.96k stars 135 forks source link

Webpack watch mode removes newly created file #157

Closed yaodingyd closed 5 years ago

yaodingyd commented 5 years ago

Issue description or question

My webpack config has two entries, client and server, and client build uses CleanWebpackPlugin. When using webpack in watch mode, it not only deletes the old output files, but also deletes the newly created server.js file. This issue occur for none watch mode.

Interestingly, I added a file watcher using chokidar for dist directory and here is what I found, for no-watch mode:

unlink dist/client.js
unlink dist/server.js
add dist/client.js
add dist/server.js

for watch mode:

change dist/server.js
unlink dist/server.js
change server.js

Seems like in watch mode CleanWebpackPlugin doesn't really remove old files?

Webpack Config

{[
    {
      mode,
      entry: {
        client: path.join(__dirname, 'src/client/index.js'),
      },
      output: {
        path: path.join(__dirname, 'dist')     
      },
      plugins: [
        new CleanWebpackPlugin(['dist']),
      ],
    },
    {
      mode,
      entry: {
        server: path.join(__dirname, 'src/server/index.js'),
      },
      output: {
        path: path.join(__dirname, 'dist')    
      },
      target: 'node',
    },
  ]};

Environment

  System:
    OS: macOS 10.14.6
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
    Memory: 1.19 GB / 16.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 12.4.0 - ~/.nvm/versions/node/v12.4.0/bin/node
    Yarn: 1.17.3 - ~/.yarn/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v12.4.0/bin/npm
  npmPackages:
    clean-webpack-plugin: 3.0.0 => 3.0.0
    webpack: 4.39.1 => 4.28.4
chrisblossom commented 5 years ago

The issue is happening because you have a shared output.path. I would highly recommend against this because it can cause other unknown issues.

I'd recommend something like this:

[
    {
        mode,
        entry: {
            client: path.join(__dirname, 'src/client/index.js'),
        },
        output: {
            path: path.join(__dirname, 'dist/client/'),
        },
        plugins: [new CleanWebpackPlugin()],
    },
    {
        mode,
        entry: {
            server: path.join(__dirname, 'src/server/index.js'),
        },
        output: {
            path: path.join(__dirname, 'dist/server/'),
        },
        target: 'node',
        plugins: [new CleanWebpackPlugin()], // each instance should clean itself
    },
];

If you insist on keeping them in the same output.path, you can try:

new CleanWebpackPlugin({
    cleanOnceBeforeBuildPatterns: ['**/*', '!server.js']
});

This will only work if you if your server code will not produce more than one bundle file.

See also: https://github.com/johnagan/clean-webpack-plugin/issues/106 #122 https://github.com/johnagan/clean-webpack-plugin/pull/129