diff --git a/libs/native-federation-core/src/build.ts b/libs/native-federation-core/src/build.ts index 3398267f..d22d8a46 100644 --- a/libs/native-federation-core/src/build.ts +++ b/libs/native-federation-core/src/build.ts @@ -11,6 +11,7 @@ export { BuildAdapterOptions, BuildResult, BuildKind, + EntryPoint, } from './lib/core/build-adapter'; export { withNativeFederation } from './lib/config/with-native-federation'; export { buildForFederation } from './lib/core/build-for-federation'; diff --git a/libs/native-federation-esbuild/package.json b/libs/native-federation-esbuild/package.json index 9921ebce..ff4dfe45 100644 --- a/libs/native-federation-esbuild/package.json +++ b/libs/native-federation-esbuild/package.json @@ -2,6 +2,11 @@ "name": "@softarc/native-federation-esbuild", "version": "2.0.8", "type": "commonjs", + "repository": { + "type": "git", + "url": "angular-architects/module-federation-plugin.git", + "directory": "libs/native-federation-esbuild" + }, "dependencies": { "@rollup/plugin-commonjs": "^22.0.2", "@rollup/plugin-node-resolve": "^13.3.0", diff --git a/libs/native-federation-esbuild/src/lib/adapter.ts b/libs/native-federation-esbuild/src/lib/adapter.ts index 0c3a0585..cb551700 100644 --- a/libs/native-federation-esbuild/src/lib/adapter.ts +++ b/libs/native-federation-esbuild/src/lib/adapter.ts @@ -2,6 +2,8 @@ import { BuildAdapter, BuildAdapterOptions, BuildResult, + EntryPoint, + logger, } from '@softarc/native-federation/build'; import * as esbuild from 'esbuild'; import { rollup } from 'rollup'; @@ -9,6 +11,7 @@ import resolve from '@rollup/plugin-node-resolve'; import { externals } from 'rollup-plugin-node-externals'; import * as fs from 'fs'; import path from 'path'; +import { collectExports } from './collect-exports'; // eslint-disable-next-line @typescript-eslint/no-var-requires const commonjs = require('@rollup/plugin-commonjs'); @@ -24,10 +27,18 @@ export type ReplacementConfig = { file: string; }; +type EntryPointWithMeta = EntryPoint & { + meta: { + isPkg: boolean; + originalFileName: string; + }; +}; + export interface EsBuildAdapterConfig { plugins: esbuild.Plugin[]; fileReplacements?: Record; skipRollup?: boolean; + /** Identify packages for which compensating missing named exports */ compensateExports?: RegExp[]; loader?: { [ext: string]: esbuild.Loader }; } @@ -42,11 +53,17 @@ export function createEsBuildAdapter(config: EsBuildAdapterConfig) { // TODO: Do we need to prepare packages anymore as esbuild has evolved? - for (const entryPoint of entryPoints) { + const preparedEntryPoints = entryPoints as EntryPointWithMeta[]; + for (const entryPoint of preparedEntryPoints) { const isPkg = entryPoint.fileName.includes('node_modules'); const pkgName = isPkg ? inferePkgName(entryPoint.fileName) : ''; const tmpFolder = `node_modules/.tmp/${pkgName}`; + entryPoint.meta = { + originalFileName: entryPoint.fileName, + isPkg, + }; + if (isPkg) { await prepareNodePackage( entryPoint.fileName, @@ -55,13 +72,12 @@ export function createEsBuildAdapter(config: EsBuildAdapterConfig) { config, !!options.dev ); - entryPoint.fileName = tmpFolder; } } const ctx = await esbuild.context({ - entryPoints: entryPoints.map((ep) => ({ + entryPoints: preparedEntryPoints.map((ep) => ({ in: ep.fileName, out: path.parse(ep.outName).name, })), @@ -81,16 +97,18 @@ export function createEsBuildAdapter(config: EsBuildAdapterConfig) { const result = await ctx.rebuild(); const writtenFiles = writeResult(result, outdir); ctx.dispose(); + preparedEntryPoints.forEach((entryPoint) => { + const { meta, fileName, outName } = entryPoint; + const normEntryPoint = meta.originalFileName.replace(/\\/g, '/'); + if ( + meta.isPkg && + config?.compensateExports?.find((regExp) => regExp.exec(normEntryPoint)) + ) { + logger.verbose('compensate exports for ' + meta.originalFileName); + compensateExports(fileName, path.join(outdir, outName)); + } + }); return writtenFiles.map((fileName) => ({ fileName })); - - // const normEntryPoint = entryPoint.replace(/\\/g, '/'); - // if ( - // isPkg && - // config?.compensateExports?.find((regExp) => regExp.exec(normEntryPoint)) - // ) { - // logger.verbose('compensate exports for ' + tmpFolder); - // compensateExports(tmpFolder, outfile); - // } }; } @@ -110,25 +128,24 @@ function writeResult( return writtenFiles; } -// TODO: Unused, to delete? -// function compensateExports(entryPoint: string, outfile?: string): void { -// const inExports = collectExports(entryPoint); -// const outExports = outfile ? collectExports(outfile) : inExports; -// -// if (!outExports.hasDefaultExport || outExports.hasFurtherExports) { -// return; -// } -// const defaultName = outExports.defaultExportName; -// -// let exports = '/*Try to compensate missing exports*/\n\n'; -// for (const exp of inExports.exports) { -// exports += `let ${exp}$softarc = ${defaultName}.${exp};\n`; -// exports += `export { ${exp}$softarc as ${exp} };\n`; -// } -// -// const target = outfile ?? entryPoint; -// fs.appendFileSync(target, exports, 'utf-8'); -// } +function compensateExports(entryPoint: string, outfile?: string): void { + const inExports = collectExports(entryPoint); + const outExports = outfile ? collectExports(outfile) : inExports; + + if (!outExports.hasDefaultExport || outExports.hasFurtherExports) { + return; + } + const defaultName = outExports.defaultExportName; + + let exports = '/*Try to compensate missing exports*/\n\n'; + for (const exp of inExports.exports) { + exports += `let ${exp}$softarc = ${defaultName}.${exp};\n`; + exports += `export { ${exp}$softarc as ${exp} };\n`; + } + + const target = outfile ?? entryPoint; + fs.appendFileSync(target, exports, 'utf-8'); +} async function prepareNodePackage( entryPoint: string,