fix(module-federation): handle remote output paths (#30119)

## Current Behavior
`parseRemotesConfig` is naively handling detection of remote output
paths needed for standing up the single file server.


## Expected Behavior
Provide better detection of remote output paths that covers inference
and executor usage with fallback behaviour
This commit is contained in:
Colum Ferry 2025-02-20 20:54:01 +00:00 committed by GitHub
parent 46e5dcefb0
commit e643899a57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 30 additions and 12 deletions

View File

@ -8,4 +8,10 @@ export interface NxModuleFederationDevServerConfig {
sslCert?: string;
sslKey?: string;
parallel?: number;
devRemoteFindOptions?: DevRemoteFindOptions;
}
export interface DevRemoteFindOptions {
retries?: number;
retryDelay?: number;
}

View File

@ -16,8 +16,6 @@ export class NxModuleFederationPlugin implements RspackPluginInstance {
private configOverride?: NxModuleFederationConfigOverride
) {}
// Do nothing
apply(compiler: Compiler) {
if (global.NX_GRAPH_CREATION) {
return;

View File

@ -1,8 +1,10 @@
import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open';
import { StaticRemoteConfig } from '../../utils';
import { DevRemoteFindOptions } from '../models';
export async function getStaticRemotes(
remotesConfig: Record<string, StaticRemoteConfig>
remotesConfig: Record<string, StaticRemoteConfig>,
devRemoteFindOptions?: DevRemoteFindOptions
) {
const remotes = Object.keys(remotesConfig);
const findStaticRemotesPromises: Promise<string | undefined>[] = [];
@ -10,8 +12,8 @@ export async function getStaticRemotes(
findStaticRemotesPromises.push(
new Promise<string>((resolve, reject) => {
waitForPortOpen(remotesConfig[remote].port, {
retries: 5,
retryDelay: 1000,
retries: devRemoteFindOptions?.retries ?? 3,
retryDelay: devRemoteFindOptions?.retryDelay ?? 1000,
}).then(
(res) => {
resolve(undefined);

View File

@ -1,6 +1,7 @@
import { ProjectGraph } from '@nx/devkit';
import { StaticRemoteConfig } from '../../utils';
import { basename, dirname } from 'path';
import { interpolate } from 'nx/src/devkit-internals';
import { joinPathFragments, ProjectGraph } from '@nx/devkit';
import { StaticRemoteConfig } from '../../utils';
export function parseRemotesConfig(
remotes: string[] | undefined,
@ -12,11 +13,22 @@ export function parseRemotesConfig(
}
const config: Record<string, StaticRemoteConfig> = {};
for (const app of remotes) {
const outputPath =
projectGraph.nodes[app].data.targets?.['build']?.options.outputPath ??
`${workspaceRoot ? `${workspaceRoot}/` : ''}${
projectGraph.nodes[app].data.root
}/dist`; // this needs replaced with better logic for finding the output path
const projectRoot = projectGraph.nodes[app].data.root;
let outputPath = interpolate(
projectGraph.nodes[app].data.targets?.['build']?.options?.outputPath ??
projectGraph.nodes[app].data.targets?.['build']?.outputs?.[0] ??
`${workspaceRoot ? `${workspaceRoot}/` : ''}${
projectGraph.nodes[app].data.root
}/dist`,
{
projectName: projectGraph.nodes[app].data.name,
projectRoot,
workspaceRoot,
}
);
if (outputPath.startsWith(projectRoot)) {
outputPath = joinPathFragments(workspaceRoot, outputPath);
}
const basePath = dirname(outputPath);
const urlSegment = app;
const port = projectGraph.nodes[app].data.targets?.['serve']?.options.port;