diff --git a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts index 9cf8342544535c..c5b44417320c4d 100644 --- a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -1,5 +1,10 @@ import type { Schema } from './schema'; -import { readCachedProjectGraph, workspaceRoot, Workspaces } from '@nx/devkit'; +import { + logger, + readCachedProjectGraph, + workspaceRoot, + Workspaces, +} from '@nx/devkit'; import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter'; import { executeWebpackDevServerBuilder } from '../webpack-dev-server/webpack-dev-server.impl'; import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; @@ -49,8 +54,16 @@ export function executeModuleFederationDevServerBuilder( validateDevRemotes(options, workspaceProjects); const remotesToSkip = new Set( - findMatchingProjects(options.skipRemotes, projectGraph.nodes) ?? [] + findMatchingProjects(options.skipRemotes, projectGraph.nodes) ); + + if (remotesToSkip.size > 0) { + logger.info( + `Not automatically serving remotes: ${[...Array.from(remotesToSkip)].join( + ', ' + )}` + ); + } const staticRemotes = getStaticRemotes( project, context, diff --git a/packages/angular/src/builders/utilities/module-federation.ts b/packages/angular/src/builders/utilities/module-federation.ts index c7eb08d2d61391..a0b40238680c69 100644 --- a/packages/angular/src/builders/utilities/module-federation.ts +++ b/packages/angular/src/builders/utilities/module-federation.ts @@ -1,7 +1,7 @@ import { ProjectConfiguration } from 'nx/src/config/workspace-json-project-json'; import { join } from 'path'; import { existsSync, readFileSync } from 'fs'; -import { Remotes } from '@nx/devkit'; +import { logger, Remotes } from '@nx/devkit'; export function getDynamicRemotes( project: ProjectConfiguration, @@ -45,23 +45,19 @@ export function getDynamicRemotes( return []; } - const dynamicRemotes = Object.entries(parsedManifest) + const allDynamicRemotes = Object.entries(parsedManifest) .map(([remoteName]) => remoteName) .filter((r) => !remotesToSkip.has(r)); - const invalidDynamicRemotes = dynamicRemotes.filter( - (remote) => !workspaceProjects[remote] - ); - if (invalidDynamicRemotes.length) { - throw new Error( - invalidDynamicRemotes.length === 1 - ? `Invalid dynamic remote configured in "${pathToManifestFile}": ${invalidDynamicRemotes[0]}.` - : `Invalid dynamic remotes configured in "${pathToManifestFile}": ${invalidDynamicRemotes.join( - ', ' - )}.` - ); - } - return dynamicRemotes; + return allDynamicRemotes.filter((remote) => { + if (!workspaceProjects[remote]) { + logger.warn( + `Skipping serving ${remote} as it could not be found in the workspace. Ensure it is served correctly.` + ); + return false; + } + return true; + }); } export function getStaticRemotes( @@ -89,26 +85,20 @@ export function getStaticRemotes( Array.isArray(mfeConfig.remotes) && mfeConfig.remotes.length > 0 ? mfeConfig.remotes : []; - const staticRemotes = remotesConfig + const allStaticRemotes = remotesConfig .map((remoteDefinition) => Array.isArray(remoteDefinition) ? remoteDefinition[0] : remoteDefinition ) .filter((r) => !remotesToSkip.has(r)); - - const invalidStaticRemotes = staticRemotes.filter( - (remote) => !workspaceProjects[remote] - ); - if (invalidStaticRemotes.length) { - throw new Error( - invalidStaticRemotes.length === 1 - ? `Invalid static remote configured in "${mfConfigPath}": ${invalidStaticRemotes[0]}.` - : `Invalid static remotes configured in "${mfConfigPath}": ${invalidStaticRemotes.join( - ', ' - )}.` - ); - } - - return staticRemotes; + return allStaticRemotes.filter((remote) => { + if (!workspaceProjects[remote]) { + logger.warn( + `Skipping serving ${remote} as it could not be found in the workspace. Ensure it is served correctly.` + ); + return false; + } + return true; + }); } export function validateDevRemotes( diff --git a/packages/nx/src/utils/find-matching-projects.spec.ts b/packages/nx/src/utils/find-matching-projects.spec.ts index 0ad750ce5645e8..72c2b57bfe7a8a 100644 --- a/packages/nx/src/utils/find-matching-projects.spec.ts +++ b/packages/nx/src/utils/find-matching-projects.spec.ts @@ -2,8 +2,8 @@ import { findMatchingProjects, getMatchingStringsWithCache, } from './find-matching-projects'; -import minimatch = require('minimatch'); import type { ProjectGraphProjectNode } from '../config/project-graph'; +import minimatch = require('minimatch'); describe('findMatchingProjects', () => { let projectGraph: Record = { diff --git a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 892ebc92b52e60..17dfbcd539d9b3 100644 --- a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -39,11 +39,29 @@ export default async function* moduleFederationDevServer( } const remotesToSkip = new Set( - findMatchingProjects(options.skipRemotes ?? [], context.projectGraph.nodes) + findMatchingProjects(options.skipRemotes, context.projectGraph.nodes) ); + + if (remotesToSkip.size > 0) { + logger.info( + `Not automatically serving remotes: ${[...remotesToSkip.values()].join( + ', ' + )}` + ); + } const knownRemotes = (moduleFederationConfig.remotes ?? []).filter((r) => { const validRemote = Array.isArray(r) ? r[0] : r; - return !remotesToSkip.has(validRemote); + + if (remotesToSkip.has(validRemote)) { + return false; + } else if (!context.projectGraph.nodes[validRemote]) { + logger.warn( + `Skipping serving ${validRemote} as it could not be found in the workspace. Ensure it is served correctly.` + ); + return false; + } else { + return true; + } }); const remotePorts = knownRemotes.map( (r) => context.projectGraph.nodes[r].data.targets['serve'].options.port diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index 1e6929ed8febab..14a5616053152a 100644 --- a/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -46,9 +46,20 @@ export default async function* moduleFederationSsrDevServer( } const remotesToSkip = new Set(options.skipRemotes ?? []); - const knownRemotes = (moduleFederationConfig.remotes ?? []).filter( - (r) => !remotesToSkip.has(r) - ); + const knownRemotes = (moduleFederationConfig.remotes ?? []).filter((r) => { + const validRemote = Array.isArray(r) ? r[0] : r; + + if (remotesToSkip.has(validRemote)) { + return false; + } else if (!context.projectGraph.nodes[validRemote]) { + logger.warn( + `Skipping serving ${validRemote} as it could not be found in the workspace. Ensure it is served correctly.` + ); + return false; + } else { + return true; + } + }); const devServeApps = !options.devRemotes ? []