diff --git a/src/clean-webpack-plugin.test.ts b/src/clean-webpack-plugin.test.ts index 887cd2a..de9040e 100644 --- a/src/clean-webpack-plugin.test.ts +++ b/src/clean-webpack-plugin.test.ts @@ -1133,7 +1133,72 @@ describe('verbose option', () => { }); describe('webpack errors', () => { - test('does nothing when webpack errors are present', async () => { + test('does nothing when webpack errors are present on initial build', async () => { + createSrcBundle(2); + + const cleanWebpackPluginPrevious = new CleanWebpackPlugin(); + + const compilerPrevious = webpack({ + entry: entryFileFull, + output: { + path: outputPathFull, + filename: 'bundle.js', + chunkFilename: '[name].bundle.js', + }, + plugins: [cleanWebpackPluginPrevious], + }); + + expect(cleanWebpackPluginPrevious.currentAssets).toEqual([]); + + /** + * Run successful build to place files inside dist folder but not in current assets + */ + await compilerPrevious.run(); + + const cleanWebpackPlugin = new CleanWebpackPlugin({ + verbose: true, + }); + + const compiler = webpack({ + entry: entryFileFull, + output: { + path: outputPathFull, + filename: 'bundle.js', + chunkFilename: '[name].bundle.js', + }, + plugins: [cleanWebpackPlugin], + }); + + expect(sandbox.getFileListSync(outputPathFull)).toEqual([ + '1.bundle.js', + 'bundle.js', + ]); + + expect(consoleSpy.mock.calls).toEqual([]); + + /** + * remove entry file to create webpack compile error + */ + sandbox.deleteSync(entryFile); + + try { + await compiler.run(); + // eslint-disable-next-line no-empty + } catch (error) {} + + expect(sandbox.getFileListSync(outputPathFull)).toEqual([ + '1.bundle.js', + 'bundle.js', + ]); + + expect(cleanWebpackPlugin.currentAssets).toEqual([]); + + expect(consoleSpy.mock.calls).toEqual([ + ['clean-webpack-plugin: pausing due to webpack errors'], + ]); + }); + + test('does nothing when webpack errors are present on rebuild', async () => { createSrcBundle(2); const cleanWebpackPlugin = new CleanWebpackPlugin({ diff --git a/src/clean-webpack-plugin.ts b/src/clean-webpack-plugin.ts index b13f1f8..eda142c 100644 --- a/src/clean-webpack-plugin.ts +++ b/src/clean-webpack-plugin.ts @@ -1,6 +1,8 @@ import path from 'path'; import { sync as delSync } from 'del'; -import { Compiler, Stats } from 'webpack'; +import { Compiler, Stats, compilation as compilationType } from 'webpack'; + +type Compilation = compilationType.Compilation; export interface Options { /** @@ -183,12 +185,18 @@ class CleanWebpackPlugin { if (this.cleanOnceBeforeBuildPatterns.length !== 0) { if (hooks) { - hooks.compile.tap('clean-webpack-plugin', () => { - this.handleInitial(); + hooks.emit.tap('clean-webpack-plugin', (compilation) => { + this.handleInitial(compilation); }); } else { - compiler.plugin('compile', () => { - this.handleInitial(); + compiler.plugin('emit', (compilation, callback) => { + try { + this.handleInitial(compilation); + + callback(); + } catch (error) { + callback(error); + } }); } } @@ -211,11 +219,21 @@ class CleanWebpackPlugin { * * Warning: It is recommended to initially clean your build directory outside of webpack to minimize unexpected behavior. */ - handleInitial() { + handleInitial(compilation: Compilation) { if (this.initialClean) { return; } + /** + * Do not remove files if there are compilation errors + * + * Handle logging inside this.handleDone + */ + const stats = compilation.getStats(); + if (stats.hasErrors()) { + return; + } + this.initialClean = true; this.removeFiles(this.cleanOnceBeforeBuildPatterns);