From fb483994e23d40e2ffab97bf691a3202c1fd1cf6 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Mon, 2 Dec 2024 15:26:12 +0000 Subject: [PATCH 1/5] feat(module-federation): move startStaticRemotesFileServer to module-federation pacakge --- .../module-federation-dev-server/lib/index.ts | 1 - .../module-federation-dev-server.impl.ts | 8 +-- .../src/executors/utils/index.ts | 1 + .../src/executors/utils/models.ts | 7 +++ .../start-static-remotes-file-server.ts | 6 +- .../module-federation-dev-server.impl.ts | 61 +------------------ .../module-federation-dev-server.impl.ts | 61 +------------------ 7 files changed, 15 insertions(+), 130 deletions(-) create mode 100644 packages/module-federation/src/executors/utils/index.ts create mode 100644 packages/module-federation/src/executors/utils/models.ts rename packages/{angular/src/executors/module-federation-dev-server/lib => module-federation/src/executors/utils}/start-static-remotes-file-server.ts (92%) diff --git a/packages/angular/src/executors/module-federation-dev-server/lib/index.ts b/packages/angular/src/executors/module-federation-dev-server/lib/index.ts index 331719948e2b9..32299cdbefa4b 100644 --- a/packages/angular/src/executors/module-federation-dev-server/lib/index.ts +++ b/packages/angular/src/executors/module-federation-dev-server/lib/index.ts @@ -1,4 +1,3 @@ export * from './build-static-remotes'; export * from './normalize-options'; export * from './start-dev-remotes'; -export * from './start-static-remotes-file-server'; diff --git a/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index f3d5b7d4a5b34..caaa8fae74e99 100644 --- a/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -4,12 +4,7 @@ import { readProjectsConfigurationFromProjectGraph, } from '@nx/devkit'; import { type Schema } from './schema'; -import { - buildStaticRemotes, - normalizeOptions, - startRemotes, - startStaticRemotesFileServer, -} from './lib'; +import { buildStaticRemotes, normalizeOptions, startRemotes } from './lib'; import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await'; import { combineAsyncIterables, @@ -22,6 +17,7 @@ import { startRemoteProxies, parseStaticRemotesConfig, } from '@nx/module-federation/src/utils'; +import { startStaticRemotesFileServer } from '@nx/module-federation/src/executors/utils'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter'; diff --git a/packages/module-federation/src/executors/utils/index.ts b/packages/module-federation/src/executors/utils/index.ts new file mode 100644 index 0000000000000..535f111bdfeb7 --- /dev/null +++ b/packages/module-federation/src/executors/utils/index.ts @@ -0,0 +1 @@ +export * from './start-static-remotes-file-server'; diff --git a/packages/module-federation/src/executors/utils/models.ts b/packages/module-federation/src/executors/utils/models.ts new file mode 100644 index 0000000000000..4478206c38c8a --- /dev/null +++ b/packages/module-federation/src/executors/utils/models.ts @@ -0,0 +1,7 @@ +export interface StaticRemotesOptions { + staticRemotesPort?: number; + host?: string; + ssl?: boolean; + sslCert?: string; + sslKey?: string; +} diff --git a/packages/angular/src/executors/module-federation-dev-server/lib/start-static-remotes-file-server.ts b/packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts similarity index 92% rename from packages/angular/src/executors/module-federation-dev-server/lib/start-static-remotes-file-server.ts rename to packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts index c44fadee06a74..9f57fc7e2cd75 100644 --- a/packages/angular/src/executors/module-federation-dev-server/lib/start-static-remotes-file-server.ts +++ b/packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts @@ -1,14 +1,14 @@ import { type ExecutorContext, workspaceRoot } from '@nx/devkit'; -import { type Schema } from '../schema'; +import { type StaticRemotesOptions } from './models'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; import { join } from 'path'; import { cpSync } from 'fs'; -import type { StaticRemotesConfig } from '@nx/module-federation/src/utils'; +import type { StaticRemotesConfig } from '../../utils'; export function startStaticRemotesFileServer( staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, - options: Schema + options: StaticRemotesOptions ) { if ( !staticRemotesConfig.remotes || 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 086cbd5a782da..03e437b507dc5 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 @@ -14,8 +14,8 @@ import { getRemotes, startRemoteProxies, parseStaticRemotesConfig, - type StaticRemotesConfig, } from '@nx/module-federation/src/utils'; +import { startStaticRemotesFileServer } from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, createAsyncIterable, @@ -35,65 +35,6 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { }; } -function startStaticRemotesFileServer( - staticRemotesConfig: StaticRemotesConfig, - context: ExecutorContext, - options: ModuleFederationDevServerOptions -) { - if ( - !staticRemotesConfig.remotes || - staticRemotesConfig.remotes.length === 0 - ) { - return; - } - let shouldMoveToCommonLocation = false; - let commonOutputDirectory: string; - for (const app of staticRemotesConfig.remotes) { - const remoteBasePath = staticRemotesConfig.config[app].basePath; - if (!commonOutputDirectory) { - commonOutputDirectory = remoteBasePath; - } else if (commonOutputDirectory !== remoteBasePath) { - shouldMoveToCommonLocation = true; - break; - } - } - - if (shouldMoveToCommonLocation) { - commonOutputDirectory = join(workspaceRoot, 'tmp/static-remotes'); - for (const app of staticRemotesConfig.remotes) { - const remoteConfig = staticRemotesConfig.config[app]; - cpSync( - remoteConfig.outputPath, - join(commonOutputDirectory, remoteConfig.urlSegment), - { - force: true, - recursive: true, - } - ); - } - } - - const staticRemotesIter = fileServerExecutor( - { - cors: true, - watch: false, - staticFilePath: commonOutputDirectory, - parallel: false, - spa: false, - withDeps: false, - host: options.host, - port: options.staticRemotesPort, - ssl: options.ssl, - sslCert: options.sslCert, - sslKey: options.sslKey, - cacheSeconds: -1, - }, - context - ); - - return staticRemotesIter; -} - async function startRemotes( remotes: string[], context: ExecutorContext, diff --git a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 62db9b91f4a7f..5f1ac55c176f8 100644 --- a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -18,9 +18,9 @@ import { getModuleFederationConfig, getRemotes, parseStaticRemotesConfig, - type StaticRemotesConfig, startRemoteProxies, } from '@nx/module-federation/src/utils'; +import { startStaticRemotesFileServer } from '@nx/module-federation/src/executors/utils'; import { buildStaticRemotes } from '../../utils/module-federation/build-static.remotes'; import devServerExecutor from '../dev-server/dev-server.impl'; import { ModuleFederationDevServerOptions } from './schema'; @@ -35,65 +35,6 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { }; } -function startStaticRemotesFileServer( - staticRemotesConfig: StaticRemotesConfig, - context: ExecutorContext, - options: ModuleFederationDevServerOptions -) { - if ( - !staticRemotesConfig.remotes || - staticRemotesConfig.remotes.length === 0 - ) { - return; - } - let shouldMoveToCommonLocation = false; - let commonOutputDirectory: string; - for (const app of staticRemotesConfig.remotes) { - const remoteBasePath = staticRemotesConfig.config[app].basePath; - if (!commonOutputDirectory) { - commonOutputDirectory = remoteBasePath; - } else if (commonOutputDirectory !== remoteBasePath) { - shouldMoveToCommonLocation = true; - break; - } - } - - if (shouldMoveToCommonLocation) { - commonOutputDirectory = join(workspaceRoot, 'tmp/static-remotes'); - for (const app of staticRemotesConfig.remotes) { - const remoteConfig = staticRemotesConfig.config[app]; - cpSync( - remoteConfig.outputPath, - join(commonOutputDirectory, remoteConfig.urlSegment), - { - force: true, - recursive: true, - } - ); - } - } - - const staticRemotesIter = fileServerExecutor( - { - cors: true, - watch: false, - staticFilePath: commonOutputDirectory, - parallel: false, - spa: false, - withDeps: false, - host: options.host, - port: options.staticRemotesPort, - ssl: options.ssl, - sslCert: options.sslCert, - sslKey: options.sslKey, - cacheSeconds: -1, - }, - context - ); - - return staticRemotesIter; -} - async function startRemotes( remotes: string[], context: ExecutorContext, From 3a0e2e077fbb9ef6c427cbed9f3edaa38ea5ba3d Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Mon, 2 Dec 2024 15:40:46 +0000 Subject: [PATCH 2/5] feat(module-federation): move buildStaticRemotes to module-federation pacakge --- .../lib/build-static-remotes.ts | 91 ----------------- .../module-federation-dev-server/lib/index.ts | 1 - .../module-federation-dev-server.impl.ts | 7 +- .../lib/build-static-remotes.ts | 91 ----------------- .../module-federation-ssr-dev-server.impl.ts | 37 +++---- packages/module-federation/package.json | 1 + .../executors/utils/build-static-remotes.ts} | 14 +-- .../src/executors/utils/index.ts | 1 + .../src/executors/utils/models.ts | 4 + .../module-federation-dev-server.impl.ts | 8 +- .../module-federation-ssr-dev-server.impl.ts | 88 +---------------- .../module-federation-static-server.impl.ts | 2 +- .../module-federation-dev-server.impl.ts | 8 +- .../module-federation-ssr-dev-server.impl.ts | 91 +---------------- .../module-federation-static-server.impl.ts | 2 +- .../module-federation/build-static.remotes.ts | 97 ------------------- 16 files changed, 59 insertions(+), 484 deletions(-) delete mode 100644 packages/angular/src/executors/module-federation-dev-server/lib/build-static-remotes.ts delete mode 100644 packages/angular/src/executors/module-federation-ssr-dev-server/lib/build-static-remotes.ts rename packages/{react/src/utils/build-static.remotes.ts => module-federation/src/executors/utils/build-static-remotes.ts} (87%) delete mode 100644 packages/rspack/src/utils/module-federation/build-static.remotes.ts diff --git a/packages/angular/src/executors/module-federation-dev-server/lib/build-static-remotes.ts b/packages/angular/src/executors/module-federation-dev-server/lib/build-static-remotes.ts deleted file mode 100644 index 54acba1ea8455..0000000000000 --- a/packages/angular/src/executors/module-federation-dev-server/lib/build-static-remotes.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { type Schema } from '../schema'; -import { type ExecutorContext, logger } from '@nx/devkit'; -import { workspaceDataDirectory } from 'nx/src/utils/cache-directory'; -import { fork } from 'node:child_process'; -import { join } from 'node:path'; -import { createWriteStream } from 'node:fs'; -import type { StaticRemotesConfig } from '@nx/module-federation/src/utils'; - -export async function buildStaticRemotes( - staticRemotesConfig: StaticRemotesConfig, - nxBin, - context: ExecutorContext, - options: Schema -) { - if (!staticRemotesConfig.remotes.length) { - return; - } - const mappedLocationOfRemotes: Record = {}; - for (const app of staticRemotesConfig.remotes) { - mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${ - options.host - }:${options.staticRemotesPort}/${ - staticRemotesConfig.config[app].urlSegment - }`; - } - - await new Promise((res, rej) => { - logger.info( - `NX Building ${staticRemotesConfig.remotes.length} static remotes...` - ); - 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, - `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log` - ); - const stdoutStream = createWriteStream(remoteBuildLogFile); - staticProcess.stdout.on('data', (data) => { - const ANSII_CODE_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; -} diff --git a/packages/angular/src/executors/module-federation-dev-server/lib/index.ts b/packages/angular/src/executors/module-federation-dev-server/lib/index.ts index 32299cdbefa4b..2f41930a016b8 100644 --- a/packages/angular/src/executors/module-federation-dev-server/lib/index.ts +++ b/packages/angular/src/executors/module-federation-dev-server/lib/index.ts @@ -1,3 +1,2 @@ -export * from './build-static-remotes'; export * from './normalize-options'; export * from './start-dev-remotes'; diff --git a/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index caaa8fae74e99..e6096fdf72bd6 100644 --- a/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -4,7 +4,7 @@ import { readProjectsConfigurationFromProjectGraph, } from '@nx/devkit'; import { type Schema } from './schema'; -import { buildStaticRemotes, normalizeOptions, startRemotes } from './lib'; +import { normalizeOptions, startRemotes } from './lib'; import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await'; import { combineAsyncIterables, @@ -17,7 +17,10 @@ import { startRemoteProxies, parseStaticRemotesConfig, } from '@nx/module-federation/src/utils'; -import { startStaticRemotesFileServer } from '@nx/module-federation/src/executors/utils'; +import { + startStaticRemotesFileServer, + buildStaticRemotes, +} from '@nx/module-federation/src/executors/utils'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter'; diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/build-static-remotes.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/build-static-remotes.ts deleted file mode 100644 index fd026d73b4417..0000000000000 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/build-static-remotes.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { Schema } from '../schema'; -import { type ExecutorContext, logger } from '@nx/devkit'; -import { workspaceDataDirectory } from 'nx/src/utils/cache-directory'; -import { fork } from 'node:child_process'; -import { join } from 'node:path'; -import { createWriteStream } from 'node:fs'; -import type { StaticRemotesConfig } from '@nx/module-federation/src/utils'; - -export async function buildStaticRemotes( - staticRemotesConfig: StaticRemotesConfig, - nxBin, - context: ExecutorContext, - options: Schema -) { - if (!staticRemotesConfig.remotes.length) { - return; - } - const mappedLocationOfRemotes: Record = {}; - for (const app of staticRemotesConfig.remotes) { - mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${ - options.host - }:${options.staticRemotesPort}/${ - staticRemotesConfig.config[app].urlSegment - }`; - } - - await new Promise((resolve, reject) => { - logger.info( - `NX Building ${staticRemotesConfig.remotes.length} static remotes...` - ); - const staticProcess = fork( - nxBin, - [ - 'run-many', - `--target=server`, - `--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, - `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log` - ); - const stdoutStream = createWriteStream(remoteBuildLogFile); - staticProcess.stdout.on('data', (data) => { - const ANSII_CODE_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 server')) { - staticProcess.stdout.removeAllListeners('data'); - logger.info( - `NX Built ${staticRemotesConfig.remotes.length} static remotes` - ); - resolve(); - } - }); - 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) { - reject( - `Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}` - ); - } else { - resolve(); - } - }); - process.on('SIGTERM', () => staticProcess.kill('SIGTERM')); - process.on('exit', () => staticProcess.kill('SIGTERM')); - }); - - return mappedLocationOfRemotes; -} diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index 9810eba64d438..75fb2a4baa6db 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -1,31 +1,31 @@ import { executeSSRDevServerBuilder } from '@angular-devkit/build-angular'; import { type ExecutorContext, logger } from '@nx/devkit'; -import { - combineAsyncIterables, - createAsyncIterable, - mapAsyncIterable, -} from '@nx/devkit/src/utils/async-iterable'; -import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await'; -import { - getModuleFederationConfig, - getRemotes, - parseStaticSsrRemotesConfig, - startSsrRemoteProxies, -} from '@nx/module-federation/src/utils'; -import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import { existsSync } from 'fs'; -import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter'; import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; import { extname, join } from 'path'; import { getDynamicMfManifestFile, validateDevRemotes, } from '../../builders/utilities/module-federation'; -import { buildStaticRemotes } from './lib/build-static-remotes'; -import { normalizeOptions } from './lib/normalize-options'; +import type { Schema } from './schema'; +import { + getModuleFederationConfig, + getRemotes, + parseStaticSsrRemotesConfig, + startSsrRemoteProxies, +} from '@nx/module-federation/src/utils'; +import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; import { startRemotes } from './lib/start-dev-remotes'; import { startStaticRemotes } from './lib/start-static-remotes'; -import type { Schema } from './schema'; +import { + combineAsyncIterables, + createAsyncIterable, + mapAsyncIterable, +} from '@nx/devkit/src/utils/async-iterable'; +import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await'; +import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter'; +import { normalizeOptions } from './lib/normalize-options'; +import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; export async function* moduleFederationSsrDevServerExecutor( schema: Schema, @@ -113,7 +113,8 @@ export async function* moduleFederationSsrDevServerExecutor( staticRemotesConfig, nxBin, context, - options + options, + 'server' ); // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin diff --git a/packages/module-federation/package.json b/packages/module-federation/package.json index a40eb3618a568..21da73e961858 100644 --- a/packages/module-federation/package.json +++ b/packages/module-federation/package.json @@ -27,6 +27,7 @@ "tslib": "^2.3.0", "@nx/devkit": "file:../devkit", "@nx/js": "file:../js", + "@nx/web": "file:../web", "picocolors": "^1.1.0", "webpack": "5.88.0", "@rspack/core": "1.1.3", diff --git a/packages/react/src/utils/build-static.remotes.ts b/packages/module-federation/src/executors/utils/build-static-remotes.ts similarity index 87% rename from packages/react/src/utils/build-static.remotes.ts rename to packages/module-federation/src/executors/utils/build-static-remotes.ts index 946d65331d8d1..b99d8fd6610c6 100644 --- a/packages/react/src/utils/build-static.remotes.ts +++ b/packages/module-federation/src/executors/utils/build-static-remotes.ts @@ -1,7 +1,6 @@ -import { StaticRemotesConfig } from '@nx/module-federation/src/utils'; -import { ExecutorContext } from '@nx/devkit'; -import { ModuleFederationDevServerOptions } from '../executors/module-federation-dev-server/schema'; -import { logger } from 'nx/src/utils/logger'; +import { ExecutorContext, logger } from '@nx/devkit'; +import { type StaticRemotesConfig } from '../../utils'; +import { type BuildStaticRemotesOptions } from './models'; import { fork } from 'node:child_process'; import { join } from 'path'; import { workspaceDataDirectory } from 'nx/src/utils/cache-directory'; @@ -11,7 +10,8 @@ export async function buildStaticRemotes( staticRemotesConfig: StaticRemotesConfig, nxBin, context: ExecutorContext, - options: ModuleFederationDevServerOptions + options: BuildStaticRemotesOptions, + buildTarget: 'build' | 'server' = 'build' ) { if (!staticRemotesConfig.remotes.length) { return; @@ -34,7 +34,7 @@ export async function buildStaticRemotes( nxBin, [ 'run-many', - `--target=build`, + `--target=${buildTarget}`, `--projects=${staticRemotesConfig.remotes.join(',')}`, ...(context.configurationName ? [`--configuration=${context.configurationName}`] @@ -66,7 +66,7 @@ export async function buildStaticRemotes( logger.log(stdoutString); } - if (stdoutString.includes('Successfully ran target build')) { + if (stdoutString.includes(`Successfully ran target ${buildTarget}`)) { staticProcess.stdout.removeAllListeners('data'); logger.info( `NX Built ${staticRemotesConfig.remotes.length} static remotes` diff --git a/packages/module-federation/src/executors/utils/index.ts b/packages/module-federation/src/executors/utils/index.ts index 535f111bdfeb7..8c46401e6fe17 100644 --- a/packages/module-federation/src/executors/utils/index.ts +++ b/packages/module-federation/src/executors/utils/index.ts @@ -1 +1,2 @@ export * from './start-static-remotes-file-server'; +export * from './build-static-remotes'; diff --git a/packages/module-federation/src/executors/utils/models.ts b/packages/module-federation/src/executors/utils/models.ts index 4478206c38c8a..8b1ce1dafa2b4 100644 --- a/packages/module-federation/src/executors/utils/models.ts +++ b/packages/module-federation/src/executors/utils/models.ts @@ -5,3 +5,7 @@ export interface StaticRemotesOptions { sslCert?: string; sslKey?: string; } + +export interface BuildStaticRemotesOptions extends StaticRemotesOptions { + parallel?: number; +} 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 03e437b507dc5..d330501212c2c 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 @@ -15,15 +15,17 @@ import { startRemoteProxies, parseStaticRemotesConfig, } from '@nx/module-federation/src/utils'; -import { startStaticRemotesFileServer } from '@nx/module-federation/src/executors/utils'; +import { + startStaticRemotesFileServer, + buildStaticRemotes, +} from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, createAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; -import { cpSync, existsSync } from 'fs'; +import { existsSync } from 'fs'; import { extname, join } from 'path'; -import { buildStaticRemotes } from '../../utils/build-static.remotes'; function getBuildOptions(buildTarget: string, context: ExecutorContext) { const target = parseTargetString(buildTarget, context); 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 2d8369c26fe1e..17a40d3b859eb 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 @@ -16,16 +16,14 @@ import { type StaticRemotesConfig, startSsrRemoteProxies, } from '@nx/module-federation/src/utils'; - +import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, createAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; -import { fork } from 'child_process'; -import { cpSync, createWriteStream, existsSync } from 'fs'; +import { cpSync, existsSync } from 'fs'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; -import { workspaceDataDirectory } from 'nx/src/utils/cache-directory'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & { @@ -168,83 +166,6 @@ async function startRemotes( return remoteIters; } -async function buildSsrStaticRemotes( - staticRemotesConfig: StaticRemotesConfig, - nxBin, - context: ExecutorContext, - options: ModuleFederationSsrDevServerOptions -) { - if (!staticRemotesConfig.remotes.length) { - return; - } - - logger.info( - `Nx is building ${staticRemotesConfig.remotes.length} static remotes...` - ); - const mapLocationOfRemotes: Record = {}; - - for (const remoteApp of staticRemotesConfig.remotes) { - mapLocationOfRemotes[remoteApp] = `http${options.ssl ? 's' : ''}://${ - options.host - }:${options.staticRemotesPort}/${ - staticRemotesConfig.config[remoteApp].urlSegment - }`; - } - - await new Promise((resolve) => { - const childProcess = fork( - nxBin, - [ - 'run-many', - '--target=server', - '--projects', - staticRemotesConfig.remotes.join(','), - ...(context.configurationName - ? [`--configuration=${context.configurationName}`] - : []), - ...(options.parallel ? [`--parallel=${options.parallel}`] : []), - ], - { - cwd: context.root, - stdio: ['ignore', 'pipe', 'pipe', 'ipc'], - } - ); - - // Add a listener to the child process to capture the build log - const remoteBuildLogFile = join( - workspaceDataDirectory, - `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log` - ); - - const remoteBuildLogStream = createWriteStream(remoteBuildLogFile); - - childProcess.stdout.on('data', (data) => { - const ANSII_CODE_REGEX = - /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; - const stdoutString = data.toString().replace(ANSII_CODE_REGEX, ''); - remoteBuildLogStream.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 server')) { - childProcess.stdout.removeAllListeners('data'); - logger.info( - `Nx Built ${staticRemotesConfig.remotes.length} static remotes.` - ); - resolve(); - } - }); - - process.on('SIGTERM', () => childProcess.kill('SIGTERM')); - process.on('exit', () => childProcess.kill('SIGTERM')); - }); - return mapLocationOfRemotes; -} - export default async function* moduleFederationSsrDevServer( ssrDevServerOptions: ModuleFederationSsrDevServerOptions, context: ExecutorContext @@ -324,11 +245,12 @@ export default async function* moduleFederationSsrDevServer( context ); - const mappedLocationsOfStaticRemotes = await buildSsrStaticRemotes( + const mappedLocationsOfStaticRemotes = await buildStaticRemotes( staticRemotesConfig, nxBin, context, - options + options, + 'server' ); const devRemoteIters = await startRemotes( diff --git a/packages/react/src/executors/module-federation-static-server/module-federation-static-server.impl.ts b/packages/react/src/executors/module-federation-static-server/module-federation-static-server.impl.ts index db32670306f57..c48826c594af9 100644 --- a/packages/react/src/executors/module-federation-static-server/module-federation-static-server.impl.ts +++ b/packages/react/src/executors/module-federation-static-server/module-federation-static-server.impl.ts @@ -16,7 +16,7 @@ import { parseStaticRemotesConfig, StaticRemotesConfig, } from '@nx/module-federation/src/utils'; -import { buildStaticRemotes } from '../../utils/build-static.remotes'; +import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; import { fork } from 'child_process'; import type { WebpackExecutorOptions } from '@nx/webpack'; import * as process from 'node:process'; diff --git a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 5f1ac55c176f8..dda8ac4cac90d 100644 --- a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -12,7 +12,7 @@ import { } from '@nx/devkit/src/utils/async-iterable'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; -import { cpSync, existsSync } from 'fs'; +import { existsSync } from 'fs'; import { extname, join } from 'path'; import { getModuleFederationConfig, @@ -20,8 +20,10 @@ import { parseStaticRemotesConfig, startRemoteProxies, } from '@nx/module-federation/src/utils'; -import { startStaticRemotesFileServer } from '@nx/module-federation/src/executors/utils'; -import { buildStaticRemotes } from '../../utils/module-federation/build-static.remotes'; +import { + startStaticRemotesFileServer, + buildStaticRemotes, +} from '@nx/module-federation/src/executors/utils'; import devServerExecutor from '../dev-server/dev-server.impl'; import { ModuleFederationDevServerOptions } from './schema'; diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index edecccbeffb73..d557da7318246 100644 --- a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -14,19 +14,16 @@ import { type StaticRemotesConfig, startSsrRemoteProxies, } from '@nx/module-federation/src/utils'; +import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; import { RspackSsrDevServerOptions } from '../ssr-dev-server/schema'; import ssrDevServerExecutor from '../ssr-dev-server/ssr-dev-server.impl'; - import { combineAsyncIterables, createAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; -import { fork } from 'child_process'; -import { cpSync, createWriteStream, existsSync } from 'fs'; - +import { cpSync, existsSync } from 'fs'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; -import { workspaceDataDirectory } from 'nx/src/utils/cache-directory'; type ModuleFederationSsrDevServerOptions = RspackSsrDevServerOptions & { devRemotes?: ( @@ -165,85 +162,6 @@ async function startRemotes( return remoteIters; } -async function buildSsrStaticRemotes( - staticRemotesConfig: StaticRemotesConfig, - nxBin, - context: ExecutorContext, - options: ModuleFederationSsrDevServerOptions -) { - if (!staticRemotesConfig.remotes.length) { - return; - } - - logger.info( - `Nx is building ${staticRemotesConfig.remotes.length} static remotes...` - ); - const mapLocationOfRemotes: Record = {}; - - for (const remoteApp of staticRemotesConfig.remotes) { - mapLocationOfRemotes[remoteApp] = `http${options.ssl ? 's' : ''}://${ - options.host - }:${options.staticRemotesPort}/${ - staticRemotesConfig.config[remoteApp].urlSegment - }`; - } - - await new Promise((resolve) => { - const childProcess = fork( - nxBin, - [ - 'run-many', - '--target=server', - '--projects', - staticRemotesConfig.remotes.join(','), - ...(context.configurationName - ? [`--configuration=${context.configurationName}`] - : []), - ...(options.parallel ? [`--parallel=${options.parallel}`] : []), - ], - { - cwd: context.root, - stdio: ['ignore', 'pipe', 'pipe', 'ipc'], - } - ); - - // Add a listener to the child process to capture the build log - const remoteBuildLogFile = join( - workspaceDataDirectory, - // eslint-disable-next-line - `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log` - ); - - const remoteBuildLogStream = createWriteStream(remoteBuildLogFile); - - childProcess.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, ''); - remoteBuildLogStream.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 server')) { - childProcess.stdout.removeAllListeners('data'); - logger.info( - `Nx Built ${staticRemotesConfig.remotes.length} static remotes.` - ); - resolve(); - } - }); - - process.on('SIGTERM', () => childProcess.kill('SIGTERM')); - process.on('exit', () => childProcess.kill('SIGTERM')); - }); - return mapLocationOfRemotes; -} - export default async function* moduleFederationSsrDevServer( ssrDevServerOptions: ModuleFederationSsrDevServerOptions, context: ExecutorContext @@ -323,11 +241,12 @@ export default async function* moduleFederationSsrDevServer( context ); - const mappedLocationsOfStaticRemotes = await buildSsrStaticRemotes( + const mappedLocationsOfStaticRemotes = await buildStaticRemotes( staticRemotesConfig, nxBin, context, - options + options, + 'server' ); const devRemoteIters = await startRemotes( diff --git a/packages/rspack/src/executors/module-federation-static-server/module-federation-static-server.impl.ts b/packages/rspack/src/executors/module-federation-static-server/module-federation-static-server.impl.ts index 3032cd49da325..5c93f1dc1c9c3 100644 --- a/packages/rspack/src/executors/module-federation-static-server/module-federation-static-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-static-server/module-federation-static-server.impl.ts @@ -22,7 +22,7 @@ import { parseStaticRemotesConfig, StaticRemotesConfig, } from '@nx/module-federation/src/utils'; -import { buildStaticRemotes } from '../../utils/module-federation/build-static.remotes'; +import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; import { ModuleFederationDevServerOptions } from '../module-federation-dev-server/schema'; import type { RspackExecutorSchema } from '../rspack/schema'; import { ModuleFederationStaticServerSchema } from './schema'; diff --git a/packages/rspack/src/utils/module-federation/build-static.remotes.ts b/packages/rspack/src/utils/module-federation/build-static.remotes.ts deleted file mode 100644 index 2db02836bed87..0000000000000 --- a/packages/rspack/src/utils/module-federation/build-static.remotes.ts +++ /dev/null @@ -1,97 +0,0 @@ -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 = {}; - - for (const app of staticRemotesConfig.remotes) { - mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${ - options.host - }:${options.staticRemotesPort}/${ - staticRemotesConfig.config[app].urlSegment - }`; - } - - await new Promise((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; -} From 1d1f1cca42db221cccfa74dce5c0f35f21b3ebff Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Mon, 2 Dec 2024 16:25:03 +0000 Subject: [PATCH 3/5] feat(module-federation): move startSsrStaticRemotesFileServer to module-federation pacakge --- .../lib/start-static-remotes.ts | 54 ----------------- .../module-federation-ssr-dev-server.impl.ts | 8 ++- .../utils/start-static-remotes-file-server.ts | 39 ++++++++++--- .../module-federation-ssr-dev-server.impl.ts | 58 ++----------------- .../module-federation-ssr-dev-server.impl.ts | 54 ++--------------- 5 files changed, 45 insertions(+), 168 deletions(-) delete mode 100644 packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-static-remotes.ts diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-static-remotes.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-static-remotes.ts deleted file mode 100644 index 0e2d8972d740a..0000000000000 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-static-remotes.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { type ExecutorContext, workspaceRoot } from '@nx/devkit'; -import { type Schema } from '../schema'; -import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; -import { join } from 'path'; -import { cpSync, rmSync } from 'fs'; -import type { StaticRemotesConfig } from '@nx/module-federation/src/utils'; -import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable'; - -export function startStaticRemotes( - ssrStaticRemotesConfig: StaticRemotesConfig, - context: ExecutorContext, - options: Schema -) { - if (ssrStaticRemotesConfig.remotes.length === 0) { - return createAsyncIterable(({ next, done }) => { - next({ success: true }); - done(); - }); - } - - // The directories are usually generated with /browser and /server suffixes so we need to copy them to a common directory - const commonOutputDirectory = join(workspaceRoot, 'tmp/static-remotes'); - for (const app of ssrStaticRemotesConfig.remotes) { - const remoteConfig = ssrStaticRemotesConfig.config[app]; - - cpSync( - remoteConfig.outputPath, - join(commonOutputDirectory, remoteConfig.urlSegment), - { - force: true, - recursive: true, - } - ); - } - - const staticRemotesIter = fileServerExecutor( - { - cors: true, - watch: false, - staticFilePath: commonOutputDirectory, - parallel: false, - spa: false, - withDeps: false, - host: options.host, - port: options.staticRemotesPort, - ssl: options.ssl, - sslCert: options.sslCert, - sslKey: options.sslKey, - cacheSeconds: -1, - }, - context - ); - return staticRemotesIter; -} diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index 75fb2a4baa6db..be1259a2725a1 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -14,9 +14,11 @@ import { parseStaticSsrRemotesConfig, startSsrRemoteProxies, } from '@nx/module-federation/src/utils'; -import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; +import { + buildStaticRemotes, + startSsrStaticRemotesFileServer, +} from '@nx/module-federation/src/executors/utils'; import { startRemotes } from './lib/start-dev-remotes'; -import { startStaticRemotes } from './lib/start-static-remotes'; import { combineAsyncIterables, createAsyncIterable, @@ -134,7 +136,7 @@ export async function* moduleFederationSsrDevServerExecutor( context ); - const staticRemotes = startStaticRemotes( + const staticRemotes = startSsrStaticRemotesFileServer( staticRemotesConfig, context, options diff --git a/packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts b/packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts index 9f57fc7e2cd75..982c1db4acc7f 100644 --- a/packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts +++ b/packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts @@ -8,7 +8,8 @@ import type { StaticRemotesConfig } from '../../utils'; export function startStaticRemotesFileServer( staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, - options: StaticRemotesOptions + options: StaticRemotesOptions, + forceMoveToCommonLocation = false ) { if ( !staticRemotesConfig.remotes || @@ -16,15 +17,17 @@ export function startStaticRemotesFileServer( ) { return; } - let shouldMoveToCommonLocation = false; + let shouldMoveToCommonLocation = forceMoveToCommonLocation || false; let commonOutputDirectory: string; - for (const app of staticRemotesConfig.remotes) { - const remoteBasePath = staticRemotesConfig.config[app].basePath; - if (!commonOutputDirectory) { - commonOutputDirectory = remoteBasePath; - } else if (commonOutputDirectory !== remoteBasePath) { - shouldMoveToCommonLocation = true; - break; + if (!forceMoveToCommonLocation) { + for (const app of staticRemotesConfig.remotes) { + const remoteBasePath = staticRemotesConfig.config[app].basePath; + if (!commonOutputDirectory) { + commonOutputDirectory = remoteBasePath; + } else if (commonOutputDirectory !== remoteBasePath) { + shouldMoveToCommonLocation = true; + break; + } } } @@ -62,3 +65,21 @@ export function startStaticRemotesFileServer( ); return staticRemotesIter; } + +export async function* startSsrStaticRemotesFileServer( + staticRemotesConfig: StaticRemotesConfig, + context: ExecutorContext, + options: StaticRemotesOptions +) { + const staticRemotesIter = startStaticRemotesFileServer( + staticRemotesConfig, + context, + options, + true + ); + if (!staticRemotesIter) { + yield { success: true }; + return; + } + yield* staticRemotesIter; +} 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 17a40d3b859eb..d1cc990225b5a 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 @@ -13,17 +13,17 @@ import { getModuleFederationConfig, getRemotes, parseStaticSsrRemotesConfig, - type StaticRemotesConfig, startSsrRemoteProxies, } from '@nx/module-federation/src/utils'; -import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; +import { + buildStaticRemotes, + startSsrStaticRemotesFileServer, +} from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, createAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; -import { cpSync, existsSync } from 'fs'; - -import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; +import { existsSync } from 'fs'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & { @@ -67,54 +67,6 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { }; } -async function* startSsrStaticRemotesFileServer( - ssrStaticRemotesConfig: StaticRemotesConfig, - context: ExecutorContext, - options: ModuleFederationSsrDevServerOptions -): - | AsyncGenerator<{ success: boolean; baseUrl?: string }> - | AsyncIterable<{ success: boolean; baseUrl?: string }> { - if (ssrStaticRemotesConfig.remotes.length === 0) { - yield { success: true }; - return; - } - - // The directories are usually generated with /browser and /server suffixes so we need to copy them to a common directory - const commonOutputDirectory = join(workspaceRoot, 'tmp/static-remotes'); - for (const app of ssrStaticRemotesConfig.remotes) { - const remoteConfig = ssrStaticRemotesConfig.config[app]; - - cpSync( - remoteConfig.outputPath, - join(commonOutputDirectory, remoteConfig.urlSegment), - { - force: true, - recursive: true, - } - ); - } - - const staticRemotesIter = fileServerExecutor( - { - cors: true, - watch: false, - staticFilePath: commonOutputDirectory, - parallel: false, - spa: false, - withDeps: false, - host: options.host, - port: options.staticRemotesPort, - ssl: options.ssl, - sslCert: options.sslCert, - sslKey: options.sslKey, - cacheSeconds: -1, - }, - context - ); - - yield* staticRemotesIter; -} - async function startRemotes( remotes: string[], context: ExecutorContext, diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index d557da7318246..85b277034f655 100644 --- a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -11,18 +11,19 @@ import { getModuleFederationConfig, getRemotes, parseStaticSsrRemotesConfig, - type StaticRemotesConfig, startSsrRemoteProxies, } from '@nx/module-federation/src/utils'; -import { buildStaticRemotes } from '@nx/module-federation/src/executors/utils'; +import { + buildStaticRemotes, + startSsrStaticRemotesFileServer, +} from '@nx/module-federation/src/executors/utils'; import { RspackSsrDevServerOptions } from '../ssr-dev-server/schema'; import ssrDevServerExecutor from '../ssr-dev-server/ssr-dev-server.impl'; import { combineAsyncIterables, createAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; -import { cpSync, existsSync } from 'fs'; -import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; +import { existsSync } from 'fs'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; type ModuleFederationSsrDevServerOptions = RspackSsrDevServerOptions & { @@ -66,51 +67,6 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { }; } -function startSsrStaticRemotesFileServer( - ssrStaticRemotesConfig: StaticRemotesConfig, - context: ExecutorContext, - options: ModuleFederationSsrDevServerOptions -) { - if (ssrStaticRemotesConfig.remotes.length === 0) { - return; - } - - // The directories are usually generated with /browser and /server suffixes so we need to copy them to a common directory - const commonOutputDirectory = join(workspaceRoot, 'tmp/static-remotes'); - for (const app of ssrStaticRemotesConfig.remotes) { - const remoteConfig = ssrStaticRemotesConfig.config[app]; - - cpSync( - remoteConfig.outputPath, - join(commonOutputDirectory, remoteConfig.urlSegment), - { - force: true, - recursive: true, - } - ); - } - - const staticRemotesIter = fileServerExecutor( - { - cors: true, - watch: false, - staticFilePath: commonOutputDirectory, - parallel: false, - spa: false, - withDeps: false, - host: options.host, - port: options.staticRemotesPort, - ssl: options.ssl, - sslCert: options.sslCert, - sslKey: options.sslKey, - cacheSeconds: -1, - }, - context - ); - - return staticRemotesIter; -} - async function startRemotes( remotes: string[], context: ExecutorContext, From 283698cb32464213ae1dcbe58ae9f98b1ce62dd0 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Mon, 2 Dec 2024 17:33:51 +0000 Subject: [PATCH 4/5] feat(module-federation): create startRemoteIterators to encapsulate common logic --- .../lib/normalize-options.ts | 1 + .../lib/start-dev-remotes.ts | 2 +- .../module-federation-dev-server.impl.ts | 91 ++----------- .../module-federation-dev-server/schema.d.ts | 1 + .../lib/normalize-options.ts | 4 +- .../lib/start-dev-remotes.ts | 2 +- .../module-federation-ssr-dev-server.impl.ts | 97 ++------------ .../schema.d.ts | 5 + .../src/executors/utils/index.ts | 2 + .../src/executors/utils/models.ts | 27 ++++ .../executors/utils/start-remote-iterators.ts | 123 ++++++++++++++++++ .../module-federation-dev-server.impl.ts | 116 +++++------------ .../module-federation-dev-server/schema.d.ts | 16 ++- .../module-federation-ssr-dev-server.impl.ts | 114 +++++----------- .../module-federation-dev-server.impl.ts | 120 +++++------------ .../module-federation-dev-server/schema.d.ts | 7 + .../module-federation-ssr-dev-server.impl.ts | 116 +++++------------ 17 files changed, 329 insertions(+), 515 deletions(-) create mode 100644 packages/module-federation/src/executors/utils/start-remote-iterators.ts diff --git a/packages/angular/src/executors/module-federation-dev-server/lib/normalize-options.ts b/packages/angular/src/executors/module-federation-dev-server/lib/normalize-options.ts index 19f46c1ab02a4..41d63136dbfb0 100644 --- a/packages/angular/src/executors/module-federation-dev-server/lib/normalize-options.ts +++ b/packages/angular/src/executors/module-federation-dev-server/lib/normalize-options.ts @@ -26,6 +26,7 @@ export function normalizeOptions(schema: Schema): NormalizedSchema { liveReload: schema.liveReload ?? true, open: schema.open ?? false, ssl: schema.ssl ?? false, + verbose: schema.verbose ?? false, sslCert: schema.sslCert ? join(workspaceRoot, schema.sslCert) : undefined, sslKey: schema.sslKey ? join(workspaceRoot, schema.sslKey) : undefined, }; diff --git a/packages/angular/src/executors/module-federation-dev-server/lib/start-dev-remotes.ts b/packages/angular/src/executors/module-federation-dev-server/lib/start-dev-remotes.ts index 321aa6ed7a27a..58836fab8ee16 100644 --- a/packages/angular/src/executors/module-federation-dev-server/lib/start-dev-remotes.ts +++ b/packages/angular/src/executors/module-federation-dev-server/lib/start-dev-remotes.ts @@ -8,7 +8,7 @@ import { export async function startRemotes( remotes: string[], workspaceProjects: Record, - options: Schema, + options: Pick, context: ExecutorContext, target: 'serve' | 'serve-static' = 'serve' ) { diff --git a/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index e6096fdf72bd6..7575516818cb6 100644 --- a/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -11,16 +11,7 @@ import { createAsyncIterable, mapAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; -import { - getModuleFederationConfig, - getRemotes, - startRemoteProxies, - parseStaticRemotesConfig, -} from '@nx/module-federation/src/utils'; -import { - startStaticRemotesFileServer, - buildStaticRemotes, -} from '@nx/module-federation/src/executors/utils'; +import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter'; @@ -36,8 +27,6 @@ export async function* moduleFederationDevServerExecutor( schema: Schema, context: ExecutorContext ) { - // Force Node to resolve to look for the nx binary that is inside node_modules - const nxBin = require.resolve('nx/bin/nx'); const options = normalizeOptions(schema); const { projects: workspaceProjects } = @@ -100,76 +89,14 @@ export async function* moduleFederationDevServerExecutor( validateDevRemotes(options, workspaceProjects); - const moduleFederationConfig = getModuleFederationConfig( - project.targets.build.options.tsConfig, - context.root, - project.root, - 'angular' - ); - - const remoteNames = options.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ); - - const remotes = getRemotes( - remoteNames, - options.skipRemotes, - moduleFederationConfig, - { - projectName: project.name, - projectGraph: context.projectGraph, - root: context.root, - }, - pathToManifestFile - ); - - options.staticRemotesPort ??= remotes.staticRemotePort; - - // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin - process.env.NX_MF_DEV_REMOTES = JSON.stringify([ - ...( - remotes.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ) ?? [] - ).map((r) => r.replace(/-/g, '_')), - project.name.replace(/-/g, '_'), - ]); - - const staticRemotesConfig = parseStaticRemotesConfig( - [...remotes.staticRemotes, ...remotes.dynamicRemotes], - context - ); - const mappedLocationsOfStaticRemotes = await buildStaticRemotes( - staticRemotesConfig, - nxBin, - context, - options - ); - - const devRemoteIters = await startRemotes( - remotes.devRemotes, - workspaceProjects, - options, - context, - 'serve' - ); - - const staticRemotesIter = startStaticRemotesFileServer( - staticRemotesConfig, - context, - options - ); - - startRemoteProxies( - staticRemotesConfig, - mappedLocationsOfStaticRemotes, - options.ssl - ? { - pathToCert: options.sslCert, - pathToKey: options.sslKey, - } - : undefined - ); + const { remotes, staticRemotesIter, devRemoteIters } = + await startRemoteIterators( + options, + context, + startRemotes, + pathToManifestFile, + 'angular' + ); const removeBaseUrlEmission = (iter: AsyncIterable) => mapAsyncIterable(iter, (v) => ({ diff --git a/packages/angular/src/executors/module-federation-dev-server/schema.d.ts b/packages/angular/src/executors/module-federation-dev-server/schema.d.ts index c2e5f77430021..f8bcc10f31c24 100644 --- a/packages/angular/src/executors/module-federation-dev-server/schema.d.ts +++ b/packages/angular/src/executors/module-federation-dev-server/schema.d.ts @@ -43,4 +43,5 @@ export type NormalizedSchema = SchemaWithBuildTarget & { liveReload: boolean; open: boolean; ssl: boolean; + verbose: boolean; }; diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts index 70e22c1de1df4..884a4c0ff4241 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts @@ -1,8 +1,8 @@ import { workspaceRoot } from '@nx/devkit'; -import type { Schema } from '../schema'; +import type { NormalizedSchema, Schema } from '../schema'; import { join } from 'path'; -export function normalizeOptions(options: Schema): Schema { +export function normalizeOptions(options: Schema): NormalizedSchema { const devServeRemotes = !options.devRemotes ? [] : Array.isArray(options.devRemotes) diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-dev-remotes.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-dev-remotes.ts index a935b10473eb4..a0650f5eb357e 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-dev-remotes.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/start-dev-remotes.ts @@ -8,7 +8,7 @@ import { export async function startRemotes( remotes: string[], workspaceProjects: Record, - options: Schema, + options: Pick, context: ExecutorContext ) { const target = 'serve-ssr'; diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index be1259a2725a1..c53565e683605 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -8,16 +8,7 @@ import { validateDevRemotes, } from '../../builders/utilities/module-federation'; import type { Schema } from './schema'; -import { - getModuleFederationConfig, - getRemotes, - parseStaticSsrRemotesConfig, - startSsrRemoteProxies, -} from '@nx/module-federation/src/utils'; -import { - buildStaticRemotes, - startSsrStaticRemotesFileServer, -} from '@nx/module-federation/src/executors/utils'; +import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import { startRemotes } from './lib/start-dev-remotes'; import { combineAsyncIterables, @@ -33,7 +24,6 @@ export async function* moduleFederationSsrDevServerExecutor( schema: Schema, context: ExecutorContext ) { - const nxBin = require.resolve('nx/bin/nx'); const options = normalizeOptions(schema); const currIter = eachValueFrom( @@ -81,74 +71,15 @@ export async function* moduleFederationSsrDevServerExecutor( validateDevRemotes({ devRemotes: options.devRemotes }, workspaceProjects); - const moduleFederationConfig = getModuleFederationConfig( - project.targets.build.options.tsConfig, - context.root, - project.root, - 'angular' - ); - - const remoteNames = options.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ); - - const remotes = getRemotes( - remoteNames, - options.skipRemotes, - moduleFederationConfig, - { - projectName: project.name, - projectGraph: context.projectGraph, - root: context.root, - }, - pathToManifestFile - ); - - options.staticRemotesPort ??= remotes.staticRemotePort; - - const staticRemotesConfig = parseStaticSsrRemotesConfig( - [...remotes.staticRemotes, ...remotes.dynamicRemotes], - context - ); - - const mappedLocationsOfStaticRemotes = await buildStaticRemotes( - staticRemotesConfig, - nxBin, - context, - options, - 'server' - ); - - // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin - process.env.NX_MF_DEV_REMOTES = JSON.stringify([ - ...( - options.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ) ?? [] - ).map((r) => r.replace(/-/g, '_')), - project.name.replace(/-/g, '_'), - ]); - - const devRemotes = await startRemotes( - remotes.devRemotes, - workspaceProjects, - options, - context - ); - - const staticRemotes = startSsrStaticRemotesFileServer( - staticRemotesConfig, - context, - options - ); - - startSsrRemoteProxies( - staticRemotesConfig, - mappedLocationsOfStaticRemotes, - options.ssl - ? { pathToCert: options.sslCert, pathToKey: options.sslKey } - : undefined - ); + const { remotes, staticRemotesIter, devRemoteIters } = + await startRemoteIterators( + options, + context, + startRemotes, + pathToManifestFile, + 'angular', + true + ); const removeBaseUrlEmission = (iter: AsyncIterable) => mapAsyncIterable(iter, (v) => ({ @@ -157,8 +88,8 @@ export async function* moduleFederationSsrDevServerExecutor( })); const combined = combineAsyncIterables( - removeBaseUrlEmission(staticRemotes), - ...(devRemotes ? devRemotes.map(removeBaseUrlEmission) : []), + removeBaseUrlEmission(staticRemotesIter), + ...(devRemoteIters ? devRemoteIters.map(removeBaseUrlEmission) : []), createAsyncIterable<{ success: true; baseUrl: string }>( async ({ next, done }) => { if (!options.isInitialHost) { @@ -175,7 +106,7 @@ export async function* moduleFederationSsrDevServerExecutor( return; } try { - const portsToWaitFor = staticRemotes + const portsToWaitFor = staticRemotesIter ? [options.staticRemotesPort, ...remotes.remotePorts] : [...remotes.remotePorts]; await Promise.all( @@ -201,7 +132,7 @@ export async function* moduleFederationSsrDevServerExecutor( } ) ); - let refs = 2 + (devRemotes?.length ?? 0); + let refs = 2 + (devRemoteIters?.length ?? 0); for await (const result of combined) { if (result.success === false) throw new Error('Remotes failed to start'); if (result.success) refs--; diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts index 4c43a78789aae..185b6caa09dc0 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts @@ -9,3 +9,8 @@ export interface Schema extends SSRDevServerBuilderOptions { staticRemotesPort?: number; isInitialHost?: boolean; } + +export interface NormalizedSchema extends Schema { + devRemotes: DevRemoteDefinition[]; + ssl: boolean; +} diff --git a/packages/module-federation/src/executors/utils/index.ts b/packages/module-federation/src/executors/utils/index.ts index 8c46401e6fe17..916cecc631e0a 100644 --- a/packages/module-federation/src/executors/utils/index.ts +++ b/packages/module-federation/src/executors/utils/index.ts @@ -1,2 +1,4 @@ export * from './start-static-remotes-file-server'; export * from './build-static-remotes'; +export * from './start-remote-iterators'; +export { DevRemoteDefinition } from './models'; diff --git a/packages/module-federation/src/executors/utils/models.ts b/packages/module-federation/src/executors/utils/models.ts index 8b1ce1dafa2b4..362705319e66f 100644 --- a/packages/module-federation/src/executors/utils/models.ts +++ b/packages/module-federation/src/executors/utils/models.ts @@ -1,3 +1,20 @@ +import type { ProjectConfiguration, ExecutorContext } from '@nx/devkit'; + +export type DevRemoteDefinition = + | string + | { remoteName: string; configuration: string }; + +export type StartRemoteFn = ( + remotes: string[], + workspaceProjects: Record, + options: { + devRemotes: DevRemoteDefinition[]; + verbose: boolean; + }, + context: ExecutorContext, + target: 'serve' | 'serve-static' +) => Promise[]>; + export interface StaticRemotesOptions { staticRemotesPort?: number; host?: string; @@ -9,3 +26,13 @@ export interface StaticRemotesOptions { export interface BuildStaticRemotesOptions extends StaticRemotesOptions { parallel?: number; } + +export interface StartRemoteIteratorsOptions extends BuildStaticRemotesOptions { + devRemotes: DevRemoteDefinition[]; + skipRemotes?: string[]; + buildTarget?: string; + liveReload?: boolean; + open?: boolean; + ssl?: boolean; + verbose: boolean; +} diff --git a/packages/module-federation/src/executors/utils/start-remote-iterators.ts b/packages/module-federation/src/executors/utils/start-remote-iterators.ts new file mode 100644 index 0000000000000..d21245a4b1eda --- /dev/null +++ b/packages/module-federation/src/executors/utils/start-remote-iterators.ts @@ -0,0 +1,123 @@ +import { StartRemoteFn, type StartRemoteIteratorsOptions } from './models'; +import { + getModuleFederationConfig, + getRemotes, + parseStaticRemotesConfig, + parseStaticSsrRemotesConfig, + startRemoteProxies, + startSsrRemoteProxies, +} from '../../utils'; +import { buildStaticRemotes } from './build-static-remotes'; +import { + startSsrStaticRemotesFileServer, + startStaticRemotesFileServer, +} from './start-static-remotes-file-server'; +import { + type ExecutorContext, + readProjectsConfigurationFromProjectGraph, +} from '@nx/devkit'; + +export async function startRemoteIterators( + options: StartRemoteIteratorsOptions, + context: ExecutorContext, + startRemoteFn: StartRemoteFn, + pathToManifestFile: string | undefined, + pluginName: 'react' | 'angular' = 'react', + isServer = false +) { + const nxBin = require.resolve('nx/bin/nx'); + const { projects: workspaceProjects } = + readProjectsConfigurationFromProjectGraph(context.projectGraph); + const project = workspaceProjects[context.projectName]; + const moduleFederationConfig = getModuleFederationConfig( + project.targets.build.options.tsConfig, + context.root, + project.root, + pluginName + ); + + const remoteNames = options.devRemotes.map((r) => + typeof r === 'string' ? r : r.remoteName + ); + + const remotes = getRemotes( + remoteNames, + options.skipRemotes, + moduleFederationConfig, + { + projectName: project.name, + projectGraph: context.projectGraph, + root: context.root, + }, + pathToManifestFile + ); + + options.staticRemotesPort ??= remotes.staticRemotePort; + + // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin + process.env.NX_MF_DEV_REMOTES = JSON.stringify([ + ...( + remotes.devRemotes.map((r) => + typeof r === 'string' ? r : r.remoteName + ) ?? [] + ).map((r) => r.replace(/-/g, '_')), + project.name.replace(/-/g, '_'), + ]); + + const staticRemotesConfig = isServer + ? parseStaticSsrRemotesConfig( + [...remotes.staticRemotes, ...remotes.dynamicRemotes], + context + ) + : parseStaticRemotesConfig( + [...remotes.staticRemotes, ...remotes.dynamicRemotes], + context + ); + const mappedLocationsOfStaticRemotes = await buildStaticRemotes( + staticRemotesConfig, + nxBin, + context, + options, + isServer ? 'server' : 'build' + ); + + const devRemoteIters = await startRemoteFn( + remotes.devRemotes, + workspaceProjects, + options, + context, + 'serve' + ); + + const staticRemotesIter = isServer + ? startSsrStaticRemotesFileServer(staticRemotesConfig, context, options) + : startStaticRemotesFileServer(staticRemotesConfig, context, options); + + isServer + ? startSsrRemoteProxies( + staticRemotesConfig, + mappedLocationsOfStaticRemotes, + options.ssl + ? { + pathToCert: options.sslCert, + pathToKey: options.sslKey, + } + : undefined + ) + : startRemoteProxies( + staticRemotesConfig, + mappedLocationsOfStaticRemotes, + options.ssl + ? { + pathToCert: options.sslCert, + pathToKey: options.sslKey, + } + : undefined + ); + + return { + remotes, + devRemoteIters, + staticRemotesIter, + }; +} 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 d330501212c2c..e5ffcbba87fc3 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 @@ -2,23 +2,17 @@ import { ExecutorContext, logger, parseTargetString, + ProjectConfiguration, readTargetOptions, runExecutor, - workspaceRoot, } from '@nx/devkit'; import devServerExecutor from '@nx/webpack/src/executors/dev-server/dev-server.impl'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; -import { ModuleFederationDevServerOptions } from './schema'; import { - getModuleFederationConfig, - getRemotes, - startRemoteProxies, - parseStaticRemotesConfig, -} from '@nx/module-federation/src/utils'; -import { - startStaticRemotesFileServer, - buildStaticRemotes, -} from '@nx/module-federation/src/executors/utils'; + ModuleFederationDevServerOptions, + NormalizedModuleFederationDevServerOptions, +} from './schema'; +import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, createAsyncIterable, @@ -39,15 +33,18 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { async function startRemotes( remotes: string[], + workspaceProjects: Record, + options: Pick< + NormalizedModuleFederationDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + >, context: ExecutorContext, - options: ModuleFederationDevServerOptions, target: 'serve' | 'serve-static' = 'serve' ) { const remoteIters: AsyncIterable<{ success: boolean }>[] = []; for (const app of remotes) { - const remoteProjectServeTarget = - context.projectGraph.nodes[app].data.targets[target]; + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; const isUsingModuleFederationDevServerExecutor = remoteProjectServeTarget.executor.includes( 'module-federation-dev-server' @@ -94,12 +91,21 @@ async function startRemotes( return remoteIters; } +function normalizeOptions( + options: ModuleFederationDevServerOptions +): NormalizedModuleFederationDevServerOptions { + return { + ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, + }; +} + export default async function* moduleFederationDevServer( - options: ModuleFederationDevServerOptions, + schema: ModuleFederationDevServerOptions, context: ExecutorContext ): AsyncIterableIterator<{ success: boolean; baseUrl?: string }> { - // Force Node to resolve to look for the nx binary that is inside node_modules - const nxBin = require.resolve('nx/bin/nx'); + const options = normalizeOptions(schema); const currIter = options.static ? fileServerExecutor( { @@ -144,74 +150,14 @@ export default async function* moduleFederationDevServer( return yield* currIter; } - const moduleFederationConfig = getModuleFederationConfig( - buildOptions.tsConfig, - context.root, - p.root, - 'react' - ); - - const remoteNames = options.devRemotes?.map((r) => - typeof r === 'string' ? r : r.remoteName - ); - - const remotes = getRemotes( - remoteNames, - options.skipRemotes, - moduleFederationConfig, - { - projectName: context.projectName, - projectGraph: context.projectGraph, - root: context.root, - }, - pathToManifestFile - ); - options.staticRemotesPort ??= remotes.staticRemotePort; - - // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin - process.env.NX_MF_DEV_REMOTES = JSON.stringify([ - ...( - remotes.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ) ?? [] - ).map((r) => r.replace(/-/g, '_')), - p.name.replace(/-/g, '_'), - ]); - - const staticRemotesConfig = parseStaticRemotesConfig( - [...remotes.staticRemotes, ...remotes.dynamicRemotes], - context - ); - const mappedLocationsOfStaticRemotes = await buildStaticRemotes( - staticRemotesConfig, - nxBin, - context, - options - ); - - const devRemoteIters = await startRemotes( - remotes.devRemotes, - context, - options, - 'serve' - ); - - const staticRemotesIter = startStaticRemotesFileServer( - staticRemotesConfig, - context, - options - ); - - startRemoteProxies( - staticRemotesConfig, - mappedLocationsOfStaticRemotes, - options.ssl - ? { - pathToCert: join(workspaceRoot, options.sslCert), - pathToKey: join(workspaceRoot, options.sslKey), - } - : undefined - ); + const { staticRemotesIter, devRemoteIters, remotes } = + await startRemoteIterators( + options, + context, + startRemotes, + pathToManifestFile, + 'react' + ); return yield* combineAsyncIterables( currIter, diff --git a/packages/react/src/executors/module-federation-dev-server/schema.d.ts b/packages/react/src/executors/module-federation-dev-server/schema.d.ts index 38a7266e98299..61bbca581ea9d 100644 --- a/packages/react/src/executors/module-federation-dev-server/schema.d.ts +++ b/packages/react/src/executors/module-federation-dev-server/schema.d.ts @@ -1,17 +1,19 @@ import { WebDevServerOptions } from '@nx/webpack'; +import { DevRemoteDefinition } from '@nx/module-federation/src/executors/utils'; export type ModuleFederationDevServerOptions = WebDevServerOptions & { - devRemotes?: ( - | string - | { - remoteName: string; - configuration: string; - } - )[]; + devRemotes?: DevRemoteDefinition[]; skipRemotes?: string[]; static?: boolean; isInitialHost?: boolean; parallel?: number; staticRemotesPort?: number; pathToManifestFile?: string; + verbose?: boolean; }; + +export type NormalizedModuleFederationDevServerOptions = + ModuleFederationDevServerOptions & { + devRemotes: DevRemoteDefinition[]; + verbose: boolean; + }; 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 d1cc990225b5a..9e48bd91236d7 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 @@ -2,6 +2,7 @@ import { ExecutorContext, logger, parseTargetString, + ProjectConfiguration, readTargetOptions, runExecutor, workspaceRoot, @@ -10,14 +11,8 @@ import ssrDevServerExecutor from '@nx/webpack/src/executors/ssr-dev-server/ssr-d import { WebSsrDevServerOptions } from '@nx/webpack/src/executors/ssr-dev-server/schema'; import { extname, join } from 'path'; import { - getModuleFederationConfig, - getRemotes, - parseStaticSsrRemotesConfig, - startSsrRemoteProxies, -} from '@nx/module-federation/src/utils'; -import { - buildStaticRemotes, - startSsrStaticRemotesFileServer, + DevRemoteDefinition, + startRemoteIterators, } from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, @@ -44,13 +39,21 @@ type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & { sslKey?: string; sslCert?: string; isInitialHost?: boolean; + verbose?: boolean; }; +type NormalizedModuleFederationSsrDevServerOptions = + ModuleFederationSsrDevServerOptions & { + devRemotes: DevRemoteDefinition[]; + verbose: boolean; + }; function normalizeOptions( options: ModuleFederationSsrDevServerOptions -): ModuleFederationSsrDevServerOptions { +): NormalizedModuleFederationSsrDevServerOptions { return { ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, ssl: options.ssl ?? false, sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, @@ -69,14 +72,19 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { async function startRemotes( remotes: string[], - context: ExecutorContext, - options: ModuleFederationSsrDevServerOptions + workspaceProjects: Record, + options: Partial< + Pick< + ModuleFederationSsrDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + > + >, + context: ExecutorContext ) { const remoteIters: AsyncIterable<{ success: boolean }>[] = []; const target = 'serve'; for (const app of remotes) { - const remoteProjectServeTarget = - context.projectGraph.nodes[app].data.targets[target]; + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; const isUsingModuleFederationSsrDevServerExecutor = remoteProjectServeTarget.executor.includes( 'module-federation-ssr-dev-server' @@ -123,8 +131,6 @@ export default async function* moduleFederationSsrDevServer( context: ExecutorContext ) { const options = normalizeOptions(ssrDevServerOptions); - // Force Node to resolve to look for the nx binary that is inside node_modules - const nxBin = require.resolve('nx/bin/nx'); let iter: any = ssrDevServerExecutor(options, context); const projectConfig = context.projectsConfigurations.projects[context.projectName]; @@ -158,75 +164,15 @@ export default async function* moduleFederationSsrDevServer( return yield* iter; } - const moduleFederationConfig = getModuleFederationConfig( - buildOptions.tsConfig, - context.root, - projectConfig.root, - 'react' - ); - - const remoteNames = options.devRemotes?.map((remote) => - typeof remote === 'string' ? remote : remote.remoteName - ); - - const remotes = getRemotes( - remoteNames, - options.skipRemotes, - moduleFederationConfig, - { - projectName: context.projectName, - projectGraph: context.projectGraph, - root: context.root, - }, - pathToManifestFile - ); - - options.staticRemotesPort ??= remotes.staticRemotePort; - - process.env.NX_MF_DEV_REMOTES = JSON.stringify([ - ...( - remotes.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ) ?? [] - ).map((r) => r.replace(/-/g, '_')), - projectConfig.name.replace(/-/g, '_'), - ]); - - const staticRemotesConfig = parseStaticSsrRemotesConfig( - [...remotes.staticRemotes, ...remotes.dynamicRemotes], - context - ); - - const mappedLocationsOfStaticRemotes = await buildStaticRemotes( - staticRemotesConfig, - nxBin, - context, - options, - 'server' - ); - - const devRemoteIters = await startRemotes( - remotes.devRemotes, - context, - options - ); - - const staticRemotesIter = startSsrStaticRemotesFileServer( - staticRemotesConfig, - context, - options - ); - - startSsrRemoteProxies( - staticRemotesConfig, - mappedLocationsOfStaticRemotes, - options.ssl - ? { - pathToCert: options.sslCert, - pathToKey: options.sslKey, - } - : undefined - ); + const { staticRemotesIter, devRemoteIters, remotes } = + await startRemoteIterators( + options, + context, + startRemotes, + pathToManifestFile, + 'react', + true + ); const combined = combineAsyncIterables(staticRemotesIter, ...devRemoteIters); diff --git a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index dda8ac4cac90d..1b2ac9ecf86cd 100644 --- a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -2,9 +2,9 @@ import { ExecutorContext, logger, parseTargetString, + ProjectConfiguration, readTargetOptions, runExecutor, - workspaceRoot, } from '@nx/devkit'; import { combineAsyncIterables, @@ -14,18 +14,12 @@ import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.im import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import { existsSync } from 'fs'; import { extname, join } from 'path'; -import { - getModuleFederationConfig, - getRemotes, - parseStaticRemotesConfig, - startRemoteProxies, -} from '@nx/module-federation/src/utils'; -import { - startStaticRemotesFileServer, - buildStaticRemotes, -} from '@nx/module-federation/src/executors/utils'; +import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import devServerExecutor from '../dev-server/dev-server.impl'; -import { ModuleFederationDevServerOptions } from './schema'; +import { + ModuleFederationDevServerOptions, + NormalizedModuleFederationDevServerOptions, +} from './schema'; function getBuildOptions(buildTarget: string, context: ExecutorContext) { const target = parseTargetString(buildTarget, context); @@ -39,15 +33,20 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { async function startRemotes( remotes: string[], + workspaceProjects: Record, + options: Partial< + Pick< + ModuleFederationDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + > + >, context: ExecutorContext, - options: ModuleFederationDevServerOptions, target: 'serve' | 'serve-static' = 'serve' ) { const remoteIters: AsyncIterable<{ success: boolean }>[] = []; for (const app of remotes) { - const remoteProjectServeTarget = - context.projectGraph.nodes[app].data.targets[target]; + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; const isUsingModuleFederationDevServerExecutor = remoteProjectServeTarget.executor.includes( 'module-federation-dev-server' @@ -94,12 +93,21 @@ async function startRemotes( return remoteIters; } +function normalizeOptions( + options: ModuleFederationDevServerOptions +): NormalizedModuleFederationDevServerOptions { + return { + ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, + }; +} + export default async function* moduleFederationDevServer( - options: ModuleFederationDevServerOptions, + schema: ModuleFederationDevServerOptions, context: ExecutorContext ): AsyncIterableIterator<{ success: boolean; baseUrl?: string }> { - // Force Node to resolve to look for the nx binary that is inside node_modules - const nxBin = require.resolve('nx/bin/nx'); + const options = normalizeOptions(schema); const currIter = options.static ? fileServerExecutor( { @@ -144,74 +152,14 @@ export default async function* moduleFederationDevServer( return yield* currIter; } - const moduleFederationConfig = getModuleFederationConfig( - buildOptions.tsConfig, - context.root, - p.root, - 'react' - ); - - const remoteNames = options.devRemotes?.map((r) => - typeof r === 'string' ? r : r.remoteName - ); - - const remotes = getRemotes( - remoteNames, - options.skipRemotes, - moduleFederationConfig, - { - projectName: context.projectName, - projectGraph: context.projectGraph, - root: context.root, - }, - pathToManifestFile - ); - options.staticRemotesPort ??= remotes.staticRemotePort; - - // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin - process.env.NX_MF_DEV_REMOTES = JSON.stringify([ - ...( - remotes.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ) ?? [] - ).map((r) => r.replace(/-/g, '_')), - p.name.replace(/-/g, '_'), - ]); - - const staticRemotesConfig = parseStaticRemotesConfig( - [...remotes.staticRemotes, ...remotes.dynamicRemotes], - context - ); - const mappedLocationsOfStaticRemotes = await buildStaticRemotes( - staticRemotesConfig, - nxBin, - context, - options - ); - - const devRemoteIters = await startRemotes( - remotes.devRemotes, - context, - options, - 'serve' - ); - - const staticRemotesIter = startStaticRemotesFileServer( - staticRemotesConfig, - context, - options - ); - - startRemoteProxies( - staticRemotesConfig, - mappedLocationsOfStaticRemotes, - options.ssl - ? { - pathToCert: join(workspaceRoot, options.sslCert), - pathToKey: join(workspaceRoot, options.sslKey), - } - : undefined - ); + const { staticRemotesIter, devRemoteIters, remotes } = + await startRemoteIterators( + options, + context, + startRemotes, + pathToManifestFile, + 'react' + ); return yield* combineAsyncIterables( currIter, diff --git a/packages/rspack/src/executors/module-federation-dev-server/schema.d.ts b/packages/rspack/src/executors/module-federation-dev-server/schema.d.ts index 61c4c0657eb06..6df7a070173cd 100644 --- a/packages/rspack/src/executors/module-federation-dev-server/schema.d.ts +++ b/packages/rspack/src/executors/module-federation-dev-server/schema.d.ts @@ -15,4 +15,11 @@ export type ModuleFederationDevServerOptions = DevServerExecutorSchema & { parallel?: number; staticRemotesPort?: number; pathToManifestFile?: string; + verbose?: boolean; }; + +export type NormalizedModuleFederationDevServerOptions = + ModuleFederationDevServerOptions & { + devRemotes: DevServerExecutorSchema['devRemotes']; + verbose: boolean; + }; diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index 85b277034f655..8f23f0fa9ea77 100644 --- a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -2,20 +2,15 @@ import { ExecutorContext, logger, parseTargetString, + ProjectConfiguration, readTargetOptions, runExecutor, workspaceRoot, } from '@nx/devkit'; import { extname, join } from 'path'; import { - getModuleFederationConfig, - getRemotes, - parseStaticSsrRemotesConfig, - startSsrRemoteProxies, -} from '@nx/module-federation/src/utils'; -import { - buildStaticRemotes, - startSsrStaticRemotesFileServer, + DevRemoteDefinition, + startRemoteIterators, } from '@nx/module-federation/src/executors/utils'; import { RspackSsrDevServerOptions } from '../ssr-dev-server/schema'; import ssrDevServerExecutor from '../ssr-dev-server/ssr-dev-server.impl'; @@ -44,13 +39,22 @@ type ModuleFederationSsrDevServerOptions = RspackSsrDevServerOptions & { sslKey?: string; sslCert?: string; isInitialHost?: boolean; + verbose?: boolean; }; +type NormalizedModuleFederationSsrDevServerOptions = + ModuleFederationSsrDevServerOptions & { + devRemotes: DevRemoteDefinition[]; + verbose: boolean; + }; + function normalizeOptions( options: ModuleFederationSsrDevServerOptions -): ModuleFederationSsrDevServerOptions { +): NormalizedModuleFederationSsrDevServerOptions { return { ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, ssl: options.ssl ?? false, sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, @@ -69,14 +73,19 @@ function getBuildOptions(buildTarget: string, context: ExecutorContext) { async function startRemotes( remotes: string[], - context: ExecutorContext, - options: ModuleFederationSsrDevServerOptions + workspaceProjects: Record, + options: Partial< + Pick< + ModuleFederationSsrDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + > + >, + context: ExecutorContext ) { const remoteIters: AsyncIterable<{ success: boolean }>[] = []; const target = 'serve'; for (const app of remotes) { - const remoteProjectServeTarget = - context.projectGraph.nodes[app].data.targets[target]; + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; const isUsingModuleFederationSsrDevServerExecutor = remoteProjectServeTarget.executor.includes( 'module-federation-ssr-dev-server' @@ -123,8 +132,7 @@ export default async function* moduleFederationSsrDevServer( context: ExecutorContext ) { const options = normalizeOptions(ssrDevServerOptions); - // Force Node to resolve to look for the nx binary that is inside node_modules - const nxBin = require.resolve('nx/bin/nx'); + const iter = ssrDevServerExecutor(options, context); const projectConfig = context.projectsConfigurations.projects[context.projectName]; @@ -158,75 +166,15 @@ export default async function* moduleFederationSsrDevServer( return yield* iter; } - const moduleFederationConfig = getModuleFederationConfig( - buildOptions.tsConfig, - context.root, - projectConfig.root, - 'react' - ); - - const remoteNames = options.devRemotes?.map((remote) => - typeof remote === 'string' ? remote : remote.remoteName - ); - - const remotes = getRemotes( - remoteNames, - options.skipRemotes, - moduleFederationConfig, - { - projectName: context.projectName, - projectGraph: context.projectGraph, - root: context.root, - }, - pathToManifestFile - ); - - options.staticRemotesPort ??= remotes.staticRemotePort; - - process.env.NX_MF_DEV_REMOTES = JSON.stringify([ - ...( - remotes.devRemotes.map((r) => - typeof r === 'string' ? r : r.remoteName - ) ?? [] - ).map((r) => r.replace(/-/g, '_')), - projectConfig.name.replace(/-/g, '_'), - ]); - - const staticRemotesConfig = parseStaticSsrRemotesConfig( - [...remotes.staticRemotes, ...remotes.dynamicRemotes], - context - ); - - const mappedLocationsOfStaticRemotes = await buildStaticRemotes( - staticRemotesConfig, - nxBin, - context, - options, - 'server' - ); - - const devRemoteIters = await startRemotes( - remotes.devRemotes, - context, - options - ); - - const staticRemotesIter = startSsrStaticRemotesFileServer( - staticRemotesConfig, - context, - options - ); - - startSsrRemoteProxies( - staticRemotesConfig, - mappedLocationsOfStaticRemotes, - options.ssl - ? { - pathToCert: options.sslCert, - pathToKey: options.sslKey, - } - : undefined - ); + const { staticRemotesIter, devRemoteIters, remotes } = + await startRemoteIterators( + options, + context, + startRemotes, + pathToManifestFile, + 'react', + true + ); return yield* combineAsyncIterables( iter, From ca75e460dc3a84c24ac1ea68e59d8360fa642085 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Mon, 2 Dec 2024 17:56:36 +0000 Subject: [PATCH 5/5] chore(module-federation): clean up module-federation executors for react --- CODEOWNERS | 1 - .../lib/normalize-options.ts | 1 + .../schema.d.ts | 1 + .../module-federation-dev-server/lib/index.ts | 2 + .../lib/normalize-options.ts | 29 ++++ .../lib/start-remotes.ts | 62 +++++++++ .../module-federation-dev-server.impl.ts | 95 +------------- .../lib/index.ts | 2 + .../lib/normalize-options.ts | 34 +++++ .../lib/start-remotes.ts | 58 ++++++++ .../module-federation-ssr-dev-server.impl.ts | 123 +---------------- .../schema.d.ts | 29 ++++ .../module-federation-dev-server/lib/index.ts | 2 + .../lib/normalize-options.ts | 29 ++++ .../lib/start-remotes.ts | 64 +++++++++ .../module-federation-dev-server.impl.ts | 97 +------------- .../lib/index.ts | 2 + .../lib/normalize-options.ts | 34 +++++ .../lib/start-remotes.ts | 58 ++++++++ .../module-federation-ssr-dev-server.impl.ts | 124 +----------------- .../schema.d.ts | 29 ++++ 21 files changed, 450 insertions(+), 426 deletions(-) create mode 100644 packages/react/src/executors/module-federation-dev-server/lib/index.ts create mode 100644 packages/react/src/executors/module-federation-dev-server/lib/normalize-options.ts create mode 100644 packages/react/src/executors/module-federation-dev-server/lib/start-remotes.ts create mode 100644 packages/react/src/executors/module-federation-ssr-dev-server/lib/index.ts create mode 100644 packages/react/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts create mode 100644 packages/react/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts create mode 100644 packages/react/src/executors/module-federation-ssr-dev-server/schema.d.ts create mode 100644 packages/rspack/src/executors/module-federation-dev-server/lib/index.ts create mode 100644 packages/rspack/src/executors/module-federation-dev-server/lib/normalize-options.ts create mode 100644 packages/rspack/src/executors/module-federation-dev-server/lib/start-remotes.ts create mode 100644 packages/rspack/src/executors/module-federation-ssr-dev-server/lib/index.ts create mode 100644 packages/rspack/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts create mode 100644 packages/rspack/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts create mode 100644 packages/rspack/src/executors/module-federation-ssr-dev-server/schema.d.ts diff --git a/CODEOWNERS b/CODEOWNERS index b983bc355a0df..7419f6615225c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -96,7 +96,6 @@ rust-toolchain @nrwl/nx-native-reviewers /packages/webpack/** @nrwl/nx-js-reviewers /e2e/webpack/** @nrwl/nx-js-reviewers /packages/rspack/** @nrwl/nx-js-reviewers -/packages/rspack/src/utils/module-federation @nrwl/nx-js-reviewers /e2e/rspack/** @nrwl/nx-js-reviewers /packages/esbuild/** @nrwl/nx-js-reviewers /e2e/esbuild/** @nrwl/nx-js-reviewers diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts index 884a4c0ff4241..89d4a67204485 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts @@ -12,6 +12,7 @@ export function normalizeOptions(options: Schema): NormalizedSchema { return { ...options, devRemotes: devServeRemotes, + verbose: options.verbose ?? false, ssl: options.ssl ?? false, sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts b/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts index 185b6caa09dc0..821a5834dd974 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/schema.d.ts @@ -13,4 +13,5 @@ export interface Schema extends SSRDevServerBuilderOptions { export interface NormalizedSchema extends Schema { devRemotes: DevRemoteDefinition[]; ssl: boolean; + verbose: boolean; } diff --git a/packages/react/src/executors/module-federation-dev-server/lib/index.ts b/packages/react/src/executors/module-federation-dev-server/lib/index.ts new file mode 100644 index 0000000000000..7923ac83c9890 --- /dev/null +++ b/packages/react/src/executors/module-federation-dev-server/lib/index.ts @@ -0,0 +1,2 @@ +export * from './normalize-options'; +export * from './start-remotes'; diff --git a/packages/react/src/executors/module-federation-dev-server/lib/normalize-options.ts b/packages/react/src/executors/module-federation-dev-server/lib/normalize-options.ts new file mode 100644 index 0000000000000..1cebe6567eb20 --- /dev/null +++ b/packages/react/src/executors/module-federation-dev-server/lib/normalize-options.ts @@ -0,0 +1,29 @@ +import { + ExecutorContext, + parseTargetString, + readTargetOptions, +} from '@nx/devkit'; +import { + ModuleFederationDevServerOptions, + NormalizedModuleFederationDevServerOptions, +} from '../schema'; + +export function getBuildOptions(buildTarget: string, context: ExecutorContext) { + const target = parseTargetString(buildTarget, context); + + const buildOptions = readTargetOptions(target, context); + + return { + ...buildOptions, + }; +} + +export function normalizeOptions( + options: ModuleFederationDevServerOptions +): NormalizedModuleFederationDevServerOptions { + return { + ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, + }; +} diff --git a/packages/react/src/executors/module-federation-dev-server/lib/start-remotes.ts b/packages/react/src/executors/module-federation-dev-server/lib/start-remotes.ts new file mode 100644 index 0000000000000..d680317e152dc --- /dev/null +++ b/packages/react/src/executors/module-federation-dev-server/lib/start-remotes.ts @@ -0,0 +1,62 @@ +import { ExecutorContext, ProjectConfiguration, runExecutor } from '@nx/devkit'; +import { NormalizedModuleFederationDevServerOptions } from '../schema'; + +export async function startRemotes( + remotes: string[], + workspaceProjects: Record, + options: Pick< + NormalizedModuleFederationDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + >, + context: ExecutorContext, + target: 'serve' | 'serve-static' = 'serve' +) { + const remoteIters: AsyncIterable<{ success: boolean }>[] = []; + + for (const app of remotes) { + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; + const isUsingModuleFederationDevServerExecutor = + remoteProjectServeTarget.executor.includes( + 'module-federation-dev-server' + ); + + const configurationOverride = options.devRemotes?.find( + ( + r + ): r is { + remoteName: string; + configuration: string; + } => typeof r !== 'string' && r.remoteName === app + )?.configuration; + + const defaultOverrides = { + ...(options.host ? { host: options.host } : {}), + ...(options.ssl ? { ssl: options.ssl } : {}), + ...(options.sslCert ? { sslCert: options.sslCert } : {}), + ...(options.sslKey ? { sslKey: options.sslKey } : {}), + }; + const overrides = + target === 'serve' + ? { + watch: true, + ...(isUsingModuleFederationDevServerExecutor + ? { isInitialHost: false } + : {}), + ...defaultOverrides, + } + : { ...defaultOverrides }; + + remoteIters.push( + await runExecutor( + { + project: app, + target, + configuration: configurationOverride ?? context.configurationName, + }, + overrides, + context + ) + ); + } + return remoteIters; +} 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 e5ffcbba87fc3..59f01abdded67 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 @@ -1,17 +1,7 @@ -import { - ExecutorContext, - logger, - parseTargetString, - ProjectConfiguration, - readTargetOptions, - runExecutor, -} from '@nx/devkit'; +import { ExecutorContext, logger } from '@nx/devkit'; import devServerExecutor from '@nx/webpack/src/executors/dev-server/dev-server.impl'; import fileServerExecutor from '@nx/web/src/executors/file-server/file-server.impl'; -import { - ModuleFederationDevServerOptions, - NormalizedModuleFederationDevServerOptions, -} from './schema'; +import { ModuleFederationDevServerOptions } from './schema'; import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, @@ -20,86 +10,7 @@ import { import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import { existsSync } from 'fs'; import { extname, join } from 'path'; - -function getBuildOptions(buildTarget: string, context: ExecutorContext) { - const target = parseTargetString(buildTarget, context); - - const buildOptions = readTargetOptions(target, context); - - return { - ...buildOptions, - }; -} - -async function startRemotes( - remotes: string[], - workspaceProjects: Record, - options: Pick< - NormalizedModuleFederationDevServerOptions, - 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' - >, - context: ExecutorContext, - target: 'serve' | 'serve-static' = 'serve' -) { - const remoteIters: AsyncIterable<{ success: boolean }>[] = []; - - for (const app of remotes) { - const remoteProjectServeTarget = workspaceProjects[app].targets[target]; - const isUsingModuleFederationDevServerExecutor = - remoteProjectServeTarget.executor.includes( - 'module-federation-dev-server' - ); - - const configurationOverride = options.devRemotes?.find( - ( - r - ): r is { - remoteName: string; - configuration: string; - } => typeof r !== 'string' && r.remoteName === app - )?.configuration; - - const defaultOverrides = { - ...(options.host ? { host: options.host } : {}), - ...(options.ssl ? { ssl: options.ssl } : {}), - ...(options.sslCert ? { sslCert: options.sslCert } : {}), - ...(options.sslKey ? { sslKey: options.sslKey } : {}), - }; - const overrides = - target === 'serve' - ? { - watch: true, - ...(isUsingModuleFederationDevServerExecutor - ? { isInitialHost: false } - : {}), - ...defaultOverrides, - } - : { ...defaultOverrides }; - - remoteIters.push( - await runExecutor( - { - project: app, - target, - configuration: configurationOverride ?? context.configurationName, - }, - overrides, - context - ) - ); - } - return remoteIters; -} - -function normalizeOptions( - options: ModuleFederationDevServerOptions -): NormalizedModuleFederationDevServerOptions { - return { - ...options, - devRemotes: options.devRemotes ?? [], - verbose: options.verbose ?? false, - }; -} +import { getBuildOptions, normalizeOptions, startRemotes } from './lib'; export default async function* moduleFederationDevServer( schema: ModuleFederationDevServerOptions, diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/lib/index.ts b/packages/react/src/executors/module-federation-ssr-dev-server/lib/index.ts new file mode 100644 index 0000000000000..7923ac83c9890 --- /dev/null +++ b/packages/react/src/executors/module-federation-ssr-dev-server/lib/index.ts @@ -0,0 +1,2 @@ +export * from './normalize-options'; +export * from './start-remotes'; diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts b/packages/react/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts new file mode 100644 index 0000000000000..d3b030d22adcb --- /dev/null +++ b/packages/react/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts @@ -0,0 +1,34 @@ +import { + ModuleFederationSsrDevServerOptions, + NormalizedModuleFederationSsrDevServerOptions, +} from '../schema'; +import { join } from 'path'; +import { + workspaceRoot, + ExecutorContext, + parseTargetString, + readTargetOptions, +} from '@nx/devkit'; + +export function normalizeOptions( + options: ModuleFederationSsrDevServerOptions +): NormalizedModuleFederationSsrDevServerOptions { + return { + ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, + ssl: options.ssl ?? false, + sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, + sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, + }; +} + +export function getBuildOptions(buildTarget: string, context: ExecutorContext) { + const target = parseTargetString(buildTarget, context); + + const buildOptions = readTargetOptions(target, context); + + return { + ...buildOptions, + }; +} diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts b/packages/react/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts new file mode 100644 index 0000000000000..6072069beb368 --- /dev/null +++ b/packages/react/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts @@ -0,0 +1,58 @@ +import { ModuleFederationSsrDevServerOptions } from '../schema'; +import { runExecutor, ExecutorContext, ProjectConfiguration } from '@nx/devkit'; + +export async function startRemotes( + remotes: string[], + workspaceProjects: Record, + options: Partial< + Pick< + ModuleFederationSsrDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + > + >, + context: ExecutorContext +) { + const remoteIters: AsyncIterable<{ success: boolean }>[] = []; + const target = 'serve'; + for (const app of remotes) { + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; + const isUsingModuleFederationSsrDevServerExecutor = + remoteProjectServeTarget.executor.includes( + 'module-federation-ssr-dev-server' + ); + + const configurationOverride = options.devRemotes?.find( + (remote): remote is { remoteName: string; configuration: string } => + typeof remote !== 'string' && remote.remoteName === app + )?.configuration; + { + const defaultOverrides = { + ...(options.host ? { host: options.host } : {}), + ...(options.ssl ? { ssl: options.ssl } : {}), + ...(options.sslCert ? { sslCert: options.sslCert } : {}), + ...(options.sslKey ? { sslKey: options.sslKey } : {}), + }; + + const overrides = { + watch: true, + ...defaultOverrides, + ...(isUsingModuleFederationSsrDevServerExecutor + ? { isInitialHost: false } + : {}), + }; + + remoteIters.push( + await runExecutor( + { + project: app, + target, + configuration: configurationOverride ?? context.configurationName, + }, + overrides, + context + ) + ); + } + } + return remoteIters; +} 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 9e48bd91236d7..2580abb00d217 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 @@ -1,130 +1,15 @@ -import { - ExecutorContext, - logger, - parseTargetString, - ProjectConfiguration, - readTargetOptions, - runExecutor, - workspaceRoot, -} from '@nx/devkit'; +import { ExecutorContext, logger } from '@nx/devkit'; import ssrDevServerExecutor from '@nx/webpack/src/executors/ssr-dev-server/ssr-dev-server.impl'; -import { WebSsrDevServerOptions } from '@nx/webpack/src/executors/ssr-dev-server/schema'; import { extname, join } from 'path'; -import { - DevRemoteDefinition, - startRemoteIterators, -} from '@nx/module-federation/src/executors/utils'; +import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import { combineAsyncIterables, createAsyncIterable, } from '@nx/devkit/src/utils/async-iterable'; import { existsSync } from 'fs'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; - -type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & { - devRemotes?: ( - | string - | { - remoteName: string; - configuration: string; - } - )[]; - - skipRemotes?: string[]; - host: string; - pathToManifestFile?: string; - staticRemotesPort?: number; - parallel?: number; - ssl?: boolean; - sslKey?: string; - sslCert?: string; - isInitialHost?: boolean; - verbose?: boolean; -}; -type NormalizedModuleFederationSsrDevServerOptions = - ModuleFederationSsrDevServerOptions & { - devRemotes: DevRemoteDefinition[]; - verbose: boolean; - }; - -function normalizeOptions( - options: ModuleFederationSsrDevServerOptions -): NormalizedModuleFederationSsrDevServerOptions { - return { - ...options, - devRemotes: options.devRemotes ?? [], - verbose: options.verbose ?? false, - ssl: options.ssl ?? false, - sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, - sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, - }; -} - -function getBuildOptions(buildTarget: string, context: ExecutorContext) { - const target = parseTargetString(buildTarget, context); - - const buildOptions = readTargetOptions(target, context); - - return { - ...buildOptions, - }; -} - -async function startRemotes( - remotes: string[], - workspaceProjects: Record, - options: Partial< - Pick< - ModuleFederationSsrDevServerOptions, - 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' - > - >, - context: ExecutorContext -) { - const remoteIters: AsyncIterable<{ success: boolean }>[] = []; - const target = 'serve'; - for (const app of remotes) { - const remoteProjectServeTarget = workspaceProjects[app].targets[target]; - const isUsingModuleFederationSsrDevServerExecutor = - remoteProjectServeTarget.executor.includes( - 'module-federation-ssr-dev-server' - ); - - const configurationOverride = options.devRemotes?.find( - (remote): remote is { remoteName: string; configuration: string } => - typeof remote !== 'string' && remote.remoteName === app - )?.configuration; - { - const defaultOverrides = { - ...(options.host ? { host: options.host } : {}), - ...(options.ssl ? { ssl: options.ssl } : {}), - ...(options.sslCert ? { sslCert: options.sslCert } : {}), - ...(options.sslKey ? { sslKey: options.sslKey } : {}), - }; - - const overrides = { - watch: true, - ...defaultOverrides, - ...(isUsingModuleFederationSsrDevServerExecutor - ? { isInitialHost: false } - : {}), - }; - - remoteIters.push( - await runExecutor( - { - project: app, - target, - configuration: configurationOverride ?? context.configurationName, - }, - overrides, - context - ) - ); - } - } - return remoteIters; -} +import { ModuleFederationSsrDevServerOptions } from './schema'; +import { getBuildOptions, normalizeOptions, startRemotes } from './lib'; export default async function* moduleFederationSsrDevServer( ssrDevServerOptions: ModuleFederationSsrDevServerOptions, diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/schema.d.ts b/packages/react/src/executors/module-federation-ssr-dev-server/schema.d.ts new file mode 100644 index 0000000000000..d37070f0209cb --- /dev/null +++ b/packages/react/src/executors/module-federation-ssr-dev-server/schema.d.ts @@ -0,0 +1,29 @@ +import { WebSsrDevServerOptions } from '@nx/webpack/src/executors/ssr-dev-server/schema'; +import { DevRemoteDefinition } from '@nx/module-federation/src/executors/utils'; + +export type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & { + devRemotes?: ( + | string + | { + remoteName: string; + configuration: string; + } + )[]; + + skipRemotes?: string[]; + host: string; + pathToManifestFile?: string; + staticRemotesPort?: number; + parallel?: number; + ssl?: boolean; + sslKey?: string; + sslCert?: string; + isInitialHost?: boolean; + verbose?: boolean; +}; + +export type NormalizedModuleFederationSsrDevServerOptions = + ModuleFederationSsrDevServerOptions & { + devRemotes: DevRemoteDefinition[]; + verbose: boolean; + }; diff --git a/packages/rspack/src/executors/module-federation-dev-server/lib/index.ts b/packages/rspack/src/executors/module-federation-dev-server/lib/index.ts new file mode 100644 index 0000000000000..7923ac83c9890 --- /dev/null +++ b/packages/rspack/src/executors/module-federation-dev-server/lib/index.ts @@ -0,0 +1,2 @@ +export * from './normalize-options'; +export * from './start-remotes'; diff --git a/packages/rspack/src/executors/module-federation-dev-server/lib/normalize-options.ts b/packages/rspack/src/executors/module-federation-dev-server/lib/normalize-options.ts new file mode 100644 index 0000000000000..1cebe6567eb20 --- /dev/null +++ b/packages/rspack/src/executors/module-federation-dev-server/lib/normalize-options.ts @@ -0,0 +1,29 @@ +import { + ExecutorContext, + parseTargetString, + readTargetOptions, +} from '@nx/devkit'; +import { + ModuleFederationDevServerOptions, + NormalizedModuleFederationDevServerOptions, +} from '../schema'; + +export function getBuildOptions(buildTarget: string, context: ExecutorContext) { + const target = parseTargetString(buildTarget, context); + + const buildOptions = readTargetOptions(target, context); + + return { + ...buildOptions, + }; +} + +export function normalizeOptions( + options: ModuleFederationDevServerOptions +): NormalizedModuleFederationDevServerOptions { + return { + ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, + }; +} diff --git a/packages/rspack/src/executors/module-federation-dev-server/lib/start-remotes.ts b/packages/rspack/src/executors/module-federation-dev-server/lib/start-remotes.ts new file mode 100644 index 0000000000000..a64079d44a37b --- /dev/null +++ b/packages/rspack/src/executors/module-federation-dev-server/lib/start-remotes.ts @@ -0,0 +1,64 @@ +import { ModuleFederationDevServerOptions } from '../schema'; +import { ProjectConfiguration, ExecutorContext, runExecutor } from '@nx/devkit'; + +export async function startRemotes( + remotes: string[], + workspaceProjects: Record, + options: Partial< + Pick< + ModuleFederationDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + > + >, + context: ExecutorContext, + target: 'serve' | 'serve-static' = 'serve' +) { + const remoteIters: AsyncIterable<{ success: boolean }>[] = []; + + for (const app of remotes) { + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; + const isUsingModuleFederationDevServerExecutor = + remoteProjectServeTarget.executor.includes( + 'module-federation-dev-server' + ); + + const configurationOverride = options.devRemotes?.find( + ( + r + ): r is { + remoteName: string; + configuration: string; + } => typeof r !== 'string' && r.remoteName === app + )?.configuration; + + const defaultOverrides = { + ...(options.host ? { host: options.host } : {}), + ...(options.ssl ? { ssl: options.ssl } : {}), + ...(options.sslCert ? { sslCert: options.sslCert } : {}), + ...(options.sslKey ? { sslKey: options.sslKey } : {}), + }; + const overrides = + target === 'serve' + ? { + watch: true, + ...(isUsingModuleFederationDevServerExecutor + ? { isInitialHost: false } + : {}), + ...defaultOverrides, + } + : { ...defaultOverrides }; + + remoteIters.push( + await runExecutor( + { + project: app, + target, + configuration: configurationOverride ?? context.configurationName, + }, + overrides, + context + ) + ); + } + return remoteIters; +} diff --git a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 1b2ac9ecf86cd..2d00b01a3eae6 100644 --- a/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -1,11 +1,4 @@ -import { - ExecutorContext, - logger, - parseTargetString, - ProjectConfiguration, - readTargetOptions, - runExecutor, -} from '@nx/devkit'; +import { ExecutorContext, logger } from '@nx/devkit'; import { combineAsyncIterables, createAsyncIterable, @@ -16,92 +9,8 @@ import { existsSync } from 'fs'; import { extname, join } from 'path'; import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import devServerExecutor from '../dev-server/dev-server.impl'; -import { - ModuleFederationDevServerOptions, - NormalizedModuleFederationDevServerOptions, -} from './schema'; - -function getBuildOptions(buildTarget: string, context: ExecutorContext) { - const target = parseTargetString(buildTarget, context); - - const buildOptions = readTargetOptions(target, context); - - return { - ...buildOptions, - }; -} - -async function startRemotes( - remotes: string[], - workspaceProjects: Record, - options: Partial< - Pick< - ModuleFederationDevServerOptions, - 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' - > - >, - context: ExecutorContext, - target: 'serve' | 'serve-static' = 'serve' -) { - const remoteIters: AsyncIterable<{ success: boolean }>[] = []; - - for (const app of remotes) { - const remoteProjectServeTarget = workspaceProjects[app].targets[target]; - const isUsingModuleFederationDevServerExecutor = - remoteProjectServeTarget.executor.includes( - 'module-federation-dev-server' - ); - - const configurationOverride = options.devRemotes?.find( - ( - r - ): r is { - remoteName: string; - configuration: string; - } => typeof r !== 'string' && r.remoteName === app - )?.configuration; - - const defaultOverrides = { - ...(options.host ? { host: options.host } : {}), - ...(options.ssl ? { ssl: options.ssl } : {}), - ...(options.sslCert ? { sslCert: options.sslCert } : {}), - ...(options.sslKey ? { sslKey: options.sslKey } : {}), - }; - const overrides = - target === 'serve' - ? { - watch: true, - ...(isUsingModuleFederationDevServerExecutor - ? { isInitialHost: false } - : {}), - ...defaultOverrides, - } - : { ...defaultOverrides }; - - remoteIters.push( - await runExecutor( - { - project: app, - target, - configuration: configurationOverride ?? context.configurationName, - }, - overrides, - context - ) - ); - } - return remoteIters; -} - -function normalizeOptions( - options: ModuleFederationDevServerOptions -): NormalizedModuleFederationDevServerOptions { - return { - ...options, - devRemotes: options.devRemotes ?? [], - verbose: options.verbose ?? false, - }; -} +import { ModuleFederationDevServerOptions } from './schema'; +import { getBuildOptions, normalizeOptions, startRemotes } from './lib'; export default async function* moduleFederationDevServer( schema: ModuleFederationDevServerOptions, diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/index.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/index.ts new file mode 100644 index 0000000000000..7923ac83c9890 --- /dev/null +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/index.ts @@ -0,0 +1,2 @@ +export * from './normalize-options'; +export * from './start-remotes'; diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts new file mode 100644 index 0000000000000..d3b030d22adcb --- /dev/null +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/normalize-options.ts @@ -0,0 +1,34 @@ +import { + ModuleFederationSsrDevServerOptions, + NormalizedModuleFederationSsrDevServerOptions, +} from '../schema'; +import { join } from 'path'; +import { + workspaceRoot, + ExecutorContext, + parseTargetString, + readTargetOptions, +} from '@nx/devkit'; + +export function normalizeOptions( + options: ModuleFederationSsrDevServerOptions +): NormalizedModuleFederationSsrDevServerOptions { + return { + ...options, + devRemotes: options.devRemotes ?? [], + verbose: options.verbose ?? false, + ssl: options.ssl ?? false, + sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, + sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, + }; +} + +export function getBuildOptions(buildTarget: string, context: ExecutorContext) { + const target = parseTargetString(buildTarget, context); + + const buildOptions = readTargetOptions(target, context); + + return { + ...buildOptions, + }; +} diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts new file mode 100644 index 0000000000000..6072069beb368 --- /dev/null +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/lib/start-remotes.ts @@ -0,0 +1,58 @@ +import { ModuleFederationSsrDevServerOptions } from '../schema'; +import { runExecutor, ExecutorContext, ProjectConfiguration } from '@nx/devkit'; + +export async function startRemotes( + remotes: string[], + workspaceProjects: Record, + options: Partial< + Pick< + ModuleFederationSsrDevServerOptions, + 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' + > + >, + context: ExecutorContext +) { + const remoteIters: AsyncIterable<{ success: boolean }>[] = []; + const target = 'serve'; + for (const app of remotes) { + const remoteProjectServeTarget = workspaceProjects[app].targets[target]; + const isUsingModuleFederationSsrDevServerExecutor = + remoteProjectServeTarget.executor.includes( + 'module-federation-ssr-dev-server' + ); + + const configurationOverride = options.devRemotes?.find( + (remote): remote is { remoteName: string; configuration: string } => + typeof remote !== 'string' && remote.remoteName === app + )?.configuration; + { + const defaultOverrides = { + ...(options.host ? { host: options.host } : {}), + ...(options.ssl ? { ssl: options.ssl } : {}), + ...(options.sslCert ? { sslCert: options.sslCert } : {}), + ...(options.sslKey ? { sslKey: options.sslKey } : {}), + }; + + const overrides = { + watch: true, + ...defaultOverrides, + ...(isUsingModuleFederationSsrDevServerExecutor + ? { isInitialHost: false } + : {}), + }; + + remoteIters.push( + await runExecutor( + { + project: app, + target, + configuration: configurationOverride ?? context.configurationName, + }, + overrides, + context + ) + ); + } + } + return remoteIters; +} diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index 8f23f0fa9ea77..5e8b673ac5332 100644 --- a/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -1,18 +1,6 @@ -import { - ExecutorContext, - logger, - parseTargetString, - ProjectConfiguration, - readTargetOptions, - runExecutor, - workspaceRoot, -} from '@nx/devkit'; +import { ExecutorContext, logger } from '@nx/devkit'; import { extname, join } from 'path'; -import { - DevRemoteDefinition, - startRemoteIterators, -} from '@nx/module-federation/src/executors/utils'; -import { RspackSsrDevServerOptions } from '../ssr-dev-server/schema'; +import { startRemoteIterators } from '@nx/module-federation/src/executors/utils'; import ssrDevServerExecutor from '../ssr-dev-server/ssr-dev-server.impl'; import { combineAsyncIterables, @@ -20,112 +8,8 @@ import { } from '@nx/devkit/src/utils/async-iterable'; import { existsSync } from 'fs'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; - -type ModuleFederationSsrDevServerOptions = RspackSsrDevServerOptions & { - devRemotes?: ( - | string - | { - remoteName: string; - configuration: string; - } - )[]; - - skipRemotes?: string[]; - host: string; - pathToManifestFile?: string; - staticRemotesPort?: number; - parallel?: number; - ssl?: boolean; - sslKey?: string; - sslCert?: string; - isInitialHost?: boolean; - verbose?: boolean; -}; - -type NormalizedModuleFederationSsrDevServerOptions = - ModuleFederationSsrDevServerOptions & { - devRemotes: DevRemoteDefinition[]; - verbose: boolean; - }; - -function normalizeOptions( - options: ModuleFederationSsrDevServerOptions -): NormalizedModuleFederationSsrDevServerOptions { - return { - ...options, - devRemotes: options.devRemotes ?? [], - verbose: options.verbose ?? false, - ssl: options.ssl ?? false, - sslCert: options.sslCert ? join(workspaceRoot, options.sslCert) : undefined, - sslKey: options.sslKey ? join(workspaceRoot, options.sslKey) : undefined, - }; -} - -function getBuildOptions(buildTarget: string, context: ExecutorContext) { - const target = parseTargetString(buildTarget, context); - - const buildOptions = readTargetOptions(target, context); - - return { - ...buildOptions, - }; -} - -async function startRemotes( - remotes: string[], - workspaceProjects: Record, - options: Partial< - Pick< - ModuleFederationSsrDevServerOptions, - 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose' - > - >, - context: ExecutorContext -) { - const remoteIters: AsyncIterable<{ success: boolean }>[] = []; - const target = 'serve'; - for (const app of remotes) { - const remoteProjectServeTarget = workspaceProjects[app].targets[target]; - const isUsingModuleFederationSsrDevServerExecutor = - remoteProjectServeTarget.executor.includes( - 'module-federation-ssr-dev-server' - ); - - const configurationOverride = options.devRemotes?.find( - (remote): remote is { remoteName: string; configuration: string } => - typeof remote !== 'string' && remote.remoteName === app - )?.configuration; - { - const defaultOverrides = { - ...(options.host ? { host: options.host } : {}), - ...(options.ssl ? { ssl: options.ssl } : {}), - ...(options.sslCert ? { sslCert: options.sslCert } : {}), - ...(options.sslKey ? { sslKey: options.sslKey } : {}), - }; - - const overrides = { - watch: true, - ...defaultOverrides, - ...(isUsingModuleFederationSsrDevServerExecutor - ? { isInitialHost: false } - : {}), - }; - - remoteIters.push( - await runExecutor( - { - project: app, - target, - configuration: configurationOverride ?? context.configurationName, - }, - overrides, - context - ) - ); - } - } - return remoteIters; -} +import { ModuleFederationSsrDevServerOptions } from './schema'; +import { getBuildOptions, normalizeOptions, startRemotes } from './lib'; export default async function* moduleFederationSsrDevServer( ssrDevServerOptions: ModuleFederationSsrDevServerOptions, diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.d.ts b/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.d.ts new file mode 100644 index 0000000000000..8df7a459c72e1 --- /dev/null +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.d.ts @@ -0,0 +1,29 @@ +import { DevRemoteDefinition } from '@nx/module-federation/src/executors/utils'; +import { RspackSsrDevServerOptions } from '../ssr-dev-server/schema'; + +export type ModuleFederationSsrDevServerOptions = RspackSsrDevServerOptions & { + devRemotes?: ( + | string + | { + remoteName: string; + configuration: string; + } + )[]; + + skipRemotes?: string[]; + host: string; + pathToManifestFile?: string; + staticRemotesPort?: number; + parallel?: number; + ssl?: boolean; + sslKey?: string; + sslCert?: string; + isInitialHost?: boolean; + verbose?: boolean; +}; + +export type NormalizedModuleFederationSsrDevServerOptions = + ModuleFederationSsrDevServerOptions & { + devRemotes: DevRemoteDefinition[]; + verbose: boolean; + };