@@ -19,6 +19,7 @@ const processAsyncTree = require("./util/processAsyncTree");
1919/** @typedef {import("./util/fs").StatsCallback } StatsCallback */
2020
2121/** @typedef {(function(string):boolean)|RegExp } IgnoreItem */
22+ /** @typedef {Map<string, number> } Assets */
2223/** @typedef {function(IgnoreItem): void } AddToIgnoreCallback */
2324
2425/**
@@ -40,18 +41,32 @@ const validate = createSchemaValidation(
4041 baseDataPath : "options"
4142 }
4243) ;
44+ const _10sec = 10 * 1000 ;
45+
46+ /**
47+ * marge assets map 2 into map 1
48+ * @param {Assets } as1 assets
49+ * @param {Assets } as2 assets
50+ * @returns {void }
51+ */
52+ const mergeAssets = ( as1 , as2 ) => {
53+ for ( const [ key , value1 ] of as2 ) {
54+ const value2 = as1 . get ( key ) ;
55+ if ( ! value2 || value1 > value2 ) as1 . set ( key , value1 ) ;
56+ }
57+ } ;
4358
4459/**
4560 * @param {OutputFileSystem } fs filesystem
4661 * @param {string } outputPath output path
47- * @param {Set <string> } currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
62+ * @param {Map <string, number > } currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
4863 * @param {function((Error | null)=, Set<string>=): void } callback returns the filenames of the assets that shouldn't be there
4964 * @returns {void }
5065 */
5166const getDiffToFs = ( fs , outputPath , currentAssets , callback ) => {
5267 const directories = new Set ( ) ;
5368 // get directories of assets
54- for ( const asset of currentAssets ) {
69+ for ( const [ asset ] of currentAssets ) {
5570 directories . add ( asset . replace ( / ( ^ | \/ ) [ ^ / ] * $ / , "" ) ) ;
5671 }
5772 // and all parent directories
@@ -91,13 +106,15 @@ const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
91106} ;
92107
93108/**
94- * @param {Set<string> } currentAssets assets list
95- * @param {Set<string> } oldAssets old assets list
109+ * @param {Assets } currentAssets assets list
110+ * @param {Assets } oldAssets old assets list
96111 * @returns {Set<string> } diff
97112 */
98113const getDiffToOldAssets = ( currentAssets , oldAssets ) => {
99114 const diff = new Set ( ) ;
100- for ( const asset of oldAssets ) {
115+ const now = Date . now ( ) ;
116+ for ( const [ asset , ts ] of oldAssets ) {
117+ if ( ts >= now ) continue ;
101118 if ( ! currentAssets . has ( asset ) ) diff . add ( asset ) ;
102119 }
103120 return diff ;
@@ -124,7 +141,7 @@ const doStat = (fs, filename, callback) => {
124141 * @param {Logger } logger logger
125142 * @param {Set<string> } diff filenames of the assets that shouldn't be there
126143 * @param {function(string): boolean } isKept check if the entry is ignored
127- * @param {function(Error=): void } callback callback
144+ * @param {function(Error=, Assets= ): void } callback callback
128145 * @returns {void }
129146 */
130147const applyDiff = ( fs , outputPath , dry , logger , diff , isKept , callback ) => {
@@ -137,11 +154,13 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
137154 } ;
138155 /** @typedef {{ type: "check" | "unlink" | "rmdir", filename: string, parent: { remaining: number, job: Job } | undefined } } Job */
139156 /** @type {Job[] } */
140- const jobs = Array . from ( diff , filename => ( {
157+ const jobs = Array . from ( diff . keys ( ) , filename => ( {
141158 type : "check" ,
142159 filename,
143160 parent : undefined
144161 } ) ) ;
162+ /** @type {Assets } */
163+ const keptAssets = new Map ( ) ;
145164 processAsyncTree (
146165 jobs ,
147166 10 ,
@@ -161,6 +180,7 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
161180 switch ( type ) {
162181 case "check" :
163182 if ( isKept ( filename ) ) {
183+ keptAssets . set ( filename , Date . now ( ) ) ;
164184 // do not decrement parent entry as we don't want to delete the parent
165185 log ( `${ filename } will be kept` ) ;
166186 return process . nextTick ( callback ) ;
@@ -247,7 +267,10 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
247267 break ;
248268 }
249269 } ,
250- callback
270+ err => {
271+ if ( err ) return callback ( err ) ;
272+ callback ( undefined , keptAssets ) ;
273+ }
251274 ) ;
252275} ;
253276
@@ -302,6 +325,7 @@ class CleanPlugin {
302325 // We assume that no external modification happens while the compiler is active
303326 // So we can store the old assets and only diff to them to avoid fs access on
304327 // incremental builds
328+ /** @type {undefined|Assets } */
305329 let oldAssets ;
306330
307331 compiler . hooks . emit . tapAsync (
@@ -322,7 +346,9 @@ class CleanPlugin {
322346 ) ;
323347 }
324348
325- const currentAssets = new Set ( ) ;
349+ /** @type {Assets } */
350+ const currentAssets = new Map ( ) ;
351+ const now = Date . now ( ) ;
326352 for ( const asset of Object . keys ( compilation . assets ) ) {
327353 if ( / ^ [ A - Z a - z ] : \\ | ^ \/ | ^ \\ \\ / . test ( asset ) ) continue ;
328354 let normalizedAsset ;
@@ -335,7 +361,12 @@ class CleanPlugin {
335361 ) ;
336362 } while ( newNormalizedAsset !== normalizedAsset ) ;
337363 if ( normalizedAsset . startsWith ( "../" ) ) continue ;
338- currentAssets . add ( normalizedAsset ) ;
364+ const assetInfo = compilation . assetsInfo . get ( asset ) ;
365+ if ( assetInfo && assetInfo . hotModuleReplacement ) {
366+ currentAssets . set ( normalizedAsset , now + _10sec ) ;
367+ } else {
368+ currentAssets . set ( normalizedAsset , now ) ;
369+ }
339370 }
340371
341372 const outputPath = compilation . getPath ( compiler . outputPath , { } ) ;
@@ -346,19 +377,34 @@ class CleanPlugin {
346377 return keepFn ( path ) ;
347378 } ;
348379
380+ /**
381+ * @param {Error= } err err
382+ * @param {Set<string>= } diff diff
383+ */
349384 const diffCallback = ( err , diff ) => {
350385 if ( err ) {
351386 oldAssets = undefined ;
352- return callback ( err ) ;
387+ callback ( err ) ;
388+ return ;
353389 }
354- applyDiff ( fs , outputPath , dry , logger , diff , isKept , err => {
355- if ( err ) {
356- oldAssets = undefined ;
357- } else {
358- oldAssets = currentAssets ;
390+ applyDiff (
391+ fs ,
392+ outputPath ,
393+ dry ,
394+ logger ,
395+ diff ,
396+ isKept ,
397+ ( err , notDeletedAssets ) => {
398+ if ( err ) {
399+ oldAssets = undefined ;
400+ } else {
401+ if ( oldAssets ) mergeAssets ( currentAssets , oldAssets ) ;
402+ oldAssets = currentAssets ;
403+ if ( notDeletedAssets ) mergeAssets ( oldAssets , notDeletedAssets ) ;
404+ }
405+ callback ( err ) ;
359406 }
360- callback ( err ) ;
361- } ) ;
407+ ) ;
362408 } ;
363409
364410 if ( oldAssets ) {
0 commit comments