diff --git a/libs/native-federation/src/utils/angular-esbuild-adapter.ts b/libs/native-federation/src/utils/angular-esbuild-adapter.ts index ffed4544..8e9ae93d 100644 --- a/libs/native-federation/src/utils/angular-esbuild-adapter.ts +++ b/libs/native-federation/src/utils/angular-esbuild-adapter.ts @@ -42,6 +42,7 @@ import { RebuildEvents, RebuildHubs } from './rebuild-events'; import JSON5 from 'json5'; import { isDeepStrictEqual } from 'node:util'; +import { createAwaitableCompilerPlugin } from './create-awaitable-compiler-plugin'; export type MemResultHandler = ( outfiles: esbuild.OutputFile[], @@ -270,6 +271,11 @@ async function runEsbuild( pluginOptions.styleOptions.externalDependencies = []; + const [compilerPlugin, pluginDisposed] = createAwaitableCompilerPlugin( + pluginOptions.pluginOptions, + pluginOptions.styleOptions, + ); + const config: esbuild.BuildOptions = { entryPoints: entryPoints.map((ep) => ({ in: ep.fileName, @@ -294,10 +300,7 @@ async function runEsbuild( target: target, logLimit: kind === 'shared-package' ? 1 : 0, plugins: (plugins as any) || [ - createCompilerPlugin( - pluginOptions.pluginOptions, - pluginOptions.styleOptions, - ), + compilerPlugin, ...(mappedPaths && mappedPaths.length > 0 ? [createSharedMappingsPlugin(mappedPaths)] : []), @@ -317,6 +320,7 @@ async function runEsbuild( const abortHandler = async () => { await ctx.cancel(); await ctx.dispose(); + await pluginDisposed; }; if (signal) { @@ -342,6 +346,7 @@ async function runEsbuild( } else { if (signal) signal.removeEventListener('abort', abortHandler); await ctx.dispose(); + await pluginDisposed; } return writtenFiles; } catch (error) { diff --git a/libs/native-federation/src/utils/create-awaitable-compiler-plugin.ts b/libs/native-federation/src/utils/create-awaitable-compiler-plugin.ts new file mode 100644 index 00000000..1b3e125b --- /dev/null +++ b/libs/native-federation/src/utils/create-awaitable-compiler-plugin.ts @@ -0,0 +1,40 @@ +import * as esbuild from 'esbuild'; +import { createCompilerPlugin } from '@angular/build/private'; + +type CreateCompilerPluginParams = Parameters; + +export function createAwaitableCompilerPlugin( + pluginOptions: CreateCompilerPluginParams[0], + styleOptions: CreateCompilerPluginParams[1], +): [esbuild.Plugin, Promise] { + const originalPlugin = createCompilerPlugin(pluginOptions, styleOptions); + + let resolveDispose: () => void; + const onDisposePromise = new Promise((resolve) => { + resolveDispose = resolve; + }); + + const wrappedPlugin: esbuild.Plugin = { + ...originalPlugin, + setup(build: esbuild.PluginBuild) { + // Wrap the build object to intercept onDispose + const wrappedBuild = new Proxy(build, { + get(target, prop) { + if (prop === 'onDispose') { + return (callback: () => void | Promise) => { + return target.onDispose(() => { + callback(); + resolveDispose(); + }); + }; + } + return target[prop as keyof esbuild.PluginBuild]; + }, + }); + + return originalPlugin.setup(wrappedBuild); + }, + }; + + return [wrappedPlugin, onDisposePromise]; +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 3cd628b7..cd242712 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -9,9 +9,9 @@ "experimentalDecorators": true, "esModuleInterop": true, "importHelpers": true, - "target": "es2015", + "target": "es2022", "module": "esnext", - "lib": ["es2017", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".",