From 247f98c09390c7530c1c707553a338f8f3ec8e07 Mon Sep 17 00:00:00 2001 From: Hendrik Liebau Date: Fri, 17 May 2024 14:52:46 +0200 Subject: [PATCH] Prevent race conditions during webpack compilation --- .changeset/selfish-beans-jump.md | 5 ++ .../src/webpack-rsc-server-plugin.ts | 72 +++++++++++-------- 2 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 .changeset/selfish-beans-jump.md diff --git a/.changeset/selfish-beans-jump.md b/.changeset/selfish-beans-jump.md new file mode 100644 index 0000000..5d97034 --- /dev/null +++ b/.changeset/selfish-beans-jump.md @@ -0,0 +1,5 @@ +--- +'@mfng/webpack-rsc': patch +--- + +Prevent race conditions during webpack compilation diff --git a/packages/webpack-rsc/src/webpack-rsc-server-plugin.ts b/packages/webpack-rsc/src/webpack-rsc-server-plugin.ts index f1351db..780ac12 100644 --- a/packages/webpack-rsc/src/webpack-rsc-server-plugin.ts +++ b/packages/webpack-rsc/src/webpack-rsc-server-plugin.ts @@ -131,31 +131,46 @@ export class WebpackRscServerPlugin { }); }; + let needsAdditionalPass = false; + compiler.hooks.finishMake.tapPromise( WebpackRscServerPlugin.name, async (compilation) => { this.serverManifest = {}; + const clientReferences = [...this.clientReferencesMap.keys()]; + const serverReferences = [...this.serverReferencesMap.keys()]; + const referencesBefore = [...clientReferences, ...serverReferences]; await Promise.all([ - ...Array.from(this.clientReferencesMap.keys()).map( - async (resource) => { - try { - await includeModule(compilation, resource); - } catch (error) { - this.clientReferencesMap.delete(resource); - } - }, - ), - ...Array.from(this.serverReferencesMap.keys()).map( - async (resource) => { - try { - await includeModule(compilation, resource, webpackRscLayerName); - } catch (error) { - this.serverReferencesMap.delete(resource); - } - }, - ), + ...clientReferences.map(async (resource) => { + try { + await includeModule(compilation, resource); + } catch (error) { + this.clientReferencesMap.delete(resource); + } + }), + ...serverReferences.map(async (resource) => { + try { + await includeModule(compilation, resource, webpackRscLayerName); + } catch (error) { + this.serverReferencesMap.delete(resource); + } + }), ]); + + const referencesAfter = [ + ...this.clientReferencesMap.keys(), + ...this.serverReferencesMap.keys(), + ]; + + if ( + referencesBefore.length !== referencesAfter.length || + !referencesAfter.every((reference) => + referencesBefore.includes(reference), + ) + ) { + needsAdditionalPass = true; + } }, ); @@ -191,16 +206,12 @@ export class WebpackRscServerPlugin { return; } - if (module.layer === webpackRscLayerName) { - if (isClientModule) { - void includeModule(compilation, resource).catch(() => { - this.clientReferencesMap.delete(resource); - }); - } - - if (isServerModule && !hasServerReferenceDependency(module)) { - module.addDependency(new ServerReferenceDependency()); - } + if ( + module.layer === webpackRscLayerName && + isServerModule && + !hasServerReferenceDependency(module) + ) { + module.addDependency(new ServerReferenceDependency()); } }); @@ -226,6 +237,11 @@ export class WebpackRscServerPlugin { .for(`javascript/esm`) .tap(`HarmonyModulesPlugin`, onNormalModuleFactoryParser); + compilation.hooks.needAdditionalPass.tap( + WebpackRscServerPlugin.name, + () => !(needsAdditionalPass = !needsAdditionalPass), + ); + compilation.hooks.afterOptimizeModuleIds.tap( WebpackRscServerPlugin.name, (modules) => {