- feat(module-federation): consolidate module federation utils into module-federation package - chore(module-federation): fix tests and linting <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> Our current support for Module Federation relies on utilities that are spread and duplicated across the `@nx/webpack` package and the `@nx/rspack` package. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> Now that we have a `@nx/module-federation` package, dedupe the utils and consolidate them into a single package ## Todo - [x] Migrations for React + Angular to install `@nx/module-federation` and point `ModuleFederationConfig` export to that package from webpack.config and rspack.config files
98 lines
3.3 KiB
TypeScript
98 lines
3.3 KiB
TypeScript
import { ExecutorContext } from '@nx/devkit';
|
|
import { createWriteStream } from 'fs';
|
|
import { fork } from 'node:child_process';
|
|
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
|
|
import { logger } from 'nx/src/utils/logger';
|
|
import { join } from 'path';
|
|
import { ModuleFederationDevServerOptions } from '../../executors/module-federation-dev-server/schema';
|
|
import type { StaticRemotesConfig } from '@nx/module-federation/src/utils';
|
|
|
|
export async function buildStaticRemotes(
|
|
staticRemotesConfig: StaticRemotesConfig,
|
|
nxBin,
|
|
context: ExecutorContext,
|
|
options: ModuleFederationDevServerOptions
|
|
) {
|
|
if (!staticRemotesConfig.remotes.length) {
|
|
return;
|
|
}
|
|
logger.info(
|
|
`NX Building ${staticRemotesConfig.remotes.length} static remotes...`
|
|
);
|
|
const mappedLocationOfRemotes: Record<string, string> = {};
|
|
|
|
for (const app of staticRemotesConfig.remotes) {
|
|
mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${
|
|
options.host
|
|
}:${options.staticRemotesPort}/${
|
|
staticRemotesConfig.config[app].urlSegment
|
|
}`;
|
|
}
|
|
|
|
await new Promise<void>((res, rej) => {
|
|
const staticProcess = fork(
|
|
nxBin,
|
|
[
|
|
'run-many',
|
|
`--target=build`,
|
|
`--projects=${staticRemotesConfig.remotes.join(',')}`,
|
|
...(context.configurationName
|
|
? [`--configuration=${context.configurationName}`]
|
|
: []),
|
|
...(options.parallel ? [`--parallel=${options.parallel}`] : []),
|
|
],
|
|
{
|
|
cwd: context.root,
|
|
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
|
}
|
|
);
|
|
|
|
// File to debug build failures e.g. 2024-01-01T00_00_0_0Z-build.log'
|
|
const remoteBuildLogFile = join(
|
|
workspaceDataDirectory,
|
|
// eslint-disable-next-line
|
|
`${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`
|
|
);
|
|
const stdoutStream = createWriteStream(remoteBuildLogFile);
|
|
|
|
staticProcess.stdout.on('data', (data) => {
|
|
const ANSII_CODE_REGEX =
|
|
// eslint-disable-next-line no-control-regex
|
|
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
|
const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
|
|
stdoutStream.write(stdoutString);
|
|
|
|
// in addition to writing into the stdout stream, also show error directly in console
|
|
// so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
|
|
if (stdoutString.includes('ERROR in')) {
|
|
logger.log(stdoutString);
|
|
}
|
|
|
|
if (stdoutString.includes('Successfully ran target build')) {
|
|
staticProcess.stdout.removeAllListeners('data');
|
|
logger.info(
|
|
`NX Built ${staticRemotesConfig.remotes.length} static remotes`
|
|
);
|
|
res();
|
|
}
|
|
});
|
|
staticProcess.stderr.on('data', (data) => logger.info(data.toString()));
|
|
staticProcess.once('exit', (code) => {
|
|
stdoutStream.end();
|
|
staticProcess.stdout.removeAllListeners('data');
|
|
staticProcess.stderr.removeAllListeners('data');
|
|
if (code !== 0) {
|
|
rej(
|
|
`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`
|
|
);
|
|
} else {
|
|
res();
|
|
}
|
|
});
|
|
process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
|
|
process.on('exit', () => staticProcess.kill('SIGTERM'));
|
|
});
|
|
|
|
return mappedLocationOfRemotes;
|
|
}
|