From d0bc3d9ce7ff06891069407f2c8929d0cbff9175 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 7 Nov 2023 19:12:53 -0800 Subject: [PATCH] fix(worker): workaround webpack4 fs write caching Ref #126 --- webpack/private/webpack_worker.js | 54 ++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/webpack/private/webpack_worker.js b/webpack/private/webpack_worker.js index 7175b28..0b1c417 100755 --- a/webpack/private/webpack_worker.js +++ b/webpack/private/webpack_worker.js @@ -92,26 +92,44 @@ class WebpackWorker extends WebpackCLI { this.compiler = await super.createCompiler(options, cb) this.options = options - // Necessary cache-clearing after each emit to ensure files are re-written to disk - // on each incremental build. - this.compiler.hooks.afterEmit.tap("rules_webpack", compilation => { - // The output directory will be cleaned between runs, webpack assumes the output directory will not be modified: - // Webpack5: https://github.com/webpack/webpack/blob/v5.36.2/lib/Compiler.js#L783-L788 - if (this.compiler._assetEmittingPreviousFiles) { - this.compiler._assetEmittingPreviousFiles.clear() - } + // The output directory will be cleaned between runs, however webpack assumes the + // output directory will not be modified and caches the file system state. + + // Webpack5: clear the "previously emitted" cache + // https://github.com/webpack/webpack/blob/v5.36.2/lib/Compiler.js#L783-L788 + if (this.compiler._assetEmittingPreviousFiles) { + this.compiler.hooks.afterEmit.tap("rules_webpack", () => this.compiler._assetEmittingPreviousFiles.clear()); + } else { + // Webpack4: patch the compiler to ensure all assets are re-written on each completion + const fsCache = new Map() + const fsWrites = new Set() + + // Clear the "writes" before compilation. + this.compiler.hooks.emit.tap('rules_webpack', () => fsWrites.clear()) - // Clear the full "emitting sources" cache in { + for (const [p, data] of fsCache.entries()) { + if (!fsWrites.has(p)) { + // TODO: wait for async write? + originalWriteFile.call(this.compiler.outputFileSystem, p, data, () => {}) + } + } + + // Clear the writes-done for the next compilation. + fsWrites.clear() + }) + + // TODO: clear entries when no longer outputted by webpack + } } } }