@nx/module-federation 20.2.0-beta.5 → 20.2.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,8 @@
25
25
  Nx is a build system, optimized for monorepos, with plugins for popular frameworks and tools and advanced CI capabilities including caching and distribution.
26
26
 
27
27
  This package is a [Module Federation plugin for Nx](https://nx.dev/nx-api/module-federation).
28
+ Module Federation allows developers to share code between deployed applications easier and makes team collaboration more efficient.
29
+ To learn more about Module Federation, check out the [official documentation](https://module-federation.io/).
28
30
 
29
31
  ## Getting Started
30
32
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nx/module-federation",
3
3
  "description": "The Nx Plugin for Module Federation contains executors and utilities that support building applications using Module Federation.",
4
- "version": "20.2.0-beta.5",
4
+ "version": "20.2.0-beta.7",
5
5
  "type": "commonjs",
6
6
  "repository": {
7
7
  "type": "git",
@@ -25,8 +25,9 @@
25
25
  "executors": "./executors.json",
26
26
  "dependencies": {
27
27
  "tslib": "^2.3.0",
28
- "@nx/devkit": "20.2.0-beta.5",
29
- "@nx/js": "20.2.0-beta.5",
28
+ "@nx/devkit": "20.2.0-beta.7",
29
+ "@nx/js": "20.2.0-beta.7",
30
+ "@nx/web": "20.2.0-beta.7",
30
31
  "picocolors": "^1.1.0",
31
32
  "webpack": "5.88.0",
32
33
  "@rspack/core": "1.1.3",
@@ -0,0 +1,4 @@
1
+ import { ExecutorContext } from '@nx/devkit';
2
+ import { type StaticRemotesConfig } from '../../utils';
3
+ import { type BuildStaticRemotesOptions } from './models';
4
+ export declare function buildStaticRemotes(staticRemotesConfig: StaticRemotesConfig, nxBin: any, context: ExecutorContext, options: BuildStaticRemotesOptions, buildTarget?: 'build' | 'server'): Promise<Record<string, string>>;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildStaticRemotes = buildStaticRemotes;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const node_child_process_1 = require("node:child_process");
6
+ const path_1 = require("path");
7
+ const cache_directory_1 = require("nx/src/utils/cache-directory");
8
+ const fs_1 = require("fs");
9
+ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options, buildTarget = 'build') {
10
+ if (!staticRemotesConfig.remotes.length) {
11
+ return;
12
+ }
13
+ devkit_1.logger.info(`NX Building ${staticRemotesConfig.remotes.length} static remotes...`);
14
+ const mappedLocationOfRemotes = {};
15
+ for (const app of staticRemotesConfig.remotes) {
16
+ mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig.config[app].urlSegment}`;
17
+ }
18
+ await new Promise((res, rej) => {
19
+ const staticProcess = (0, node_child_process_1.fork)(nxBin, [
20
+ 'run-many',
21
+ `--target=${buildTarget}`,
22
+ `--projects=${staticRemotesConfig.remotes.join(',')}`,
23
+ ...(context.configurationName
24
+ ? [`--configuration=${context.configurationName}`]
25
+ : []),
26
+ ...(options.parallel ? [`--parallel=${options.parallel}`] : []),
27
+ ], {
28
+ cwd: context.root,
29
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
30
+ });
31
+ // File to debug build failures e.g. 2024-01-01T00_00_0_0Z-build.log'
32
+ const remoteBuildLogFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`);
33
+ const stdoutStream = (0, fs_1.createWriteStream)(remoteBuildLogFile);
34
+ staticProcess.stdout.on('data', (data) => {
35
+ const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
36
+ const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
37
+ stdoutStream.write(stdoutString);
38
+ // in addition to writing into the stdout stream, also show error directly in console
39
+ // so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
40
+ if (stdoutString.includes('ERROR in')) {
41
+ devkit_1.logger.log(stdoutString);
42
+ }
43
+ if (stdoutString.includes(`Successfully ran target ${buildTarget}`)) {
44
+ staticProcess.stdout.removeAllListeners('data');
45
+ devkit_1.logger.info(`NX Built ${staticRemotesConfig.remotes.length} static remotes`);
46
+ res();
47
+ }
48
+ });
49
+ staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
50
+ staticProcess.once('exit', (code) => {
51
+ stdoutStream.end();
52
+ staticProcess.stdout.removeAllListeners('data');
53
+ staticProcess.stderr.removeAllListeners('data');
54
+ if (code !== 0) {
55
+ rej(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
56
+ }
57
+ else {
58
+ res();
59
+ }
60
+ });
61
+ process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
62
+ process.on('exit', () => staticProcess.kill('SIGTERM'));
63
+ });
64
+ return mappedLocationOfRemotes;
65
+ }
@@ -0,0 +1,4 @@
1
+ export * from './start-static-remotes-file-server';
2
+ export * from './build-static-remotes';
3
+ export * from './start-remote-iterators';
4
+ export { DevRemoteDefinition } from './models';
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./start-static-remotes-file-server"), exports);
5
+ tslib_1.__exportStar(require("./build-static-remotes"), exports);
6
+ tslib_1.__exportStar(require("./start-remote-iterators"), exports);
@@ -0,0 +1,30 @@
1
+ import type { ProjectConfiguration, ExecutorContext } from '@nx/devkit';
2
+ export type DevRemoteDefinition = string | {
3
+ remoteName: string;
4
+ configuration: string;
5
+ };
6
+ export type StartRemoteFn = (remotes: string[], workspaceProjects: Record<string, ProjectConfiguration>, options: {
7
+ devRemotes: DevRemoteDefinition[];
8
+ verbose: boolean;
9
+ }, context: ExecutorContext, target: 'serve' | 'serve-static') => Promise<AsyncIterable<{
10
+ success: boolean;
11
+ }>[]>;
12
+ export interface StaticRemotesOptions {
13
+ staticRemotesPort?: number;
14
+ host?: string;
15
+ ssl?: boolean;
16
+ sslCert?: string;
17
+ sslKey?: string;
18
+ }
19
+ export interface BuildStaticRemotesOptions extends StaticRemotesOptions {
20
+ parallel?: number;
21
+ }
22
+ export interface StartRemoteIteratorsOptions extends BuildStaticRemotesOptions {
23
+ devRemotes: DevRemoteDefinition[];
24
+ skipRemotes?: string[];
25
+ buildTarget?: string;
26
+ liveReload?: boolean;
27
+ open?: boolean;
28
+ ssl?: boolean;
29
+ verbose: boolean;
30
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,25 @@
1
+ import { StartRemoteFn, type StartRemoteIteratorsOptions } from './models';
2
+ import { type ExecutorContext } from '@nx/devkit';
3
+ export declare function startRemoteIterators(options: StartRemoteIteratorsOptions, context: ExecutorContext, startRemoteFn: StartRemoteFn, pathToManifestFile: string | undefined, pluginName?: 'react' | 'angular', isServer?: boolean): Promise<{
4
+ remotes: {
5
+ staticRemotes: string[];
6
+ devRemotes: any[];
7
+ dynamicRemotes: any[];
8
+ remotePorts: any[];
9
+ staticRemotePort: number;
10
+ };
11
+ devRemoteIters: AsyncIterable<{
12
+ success: boolean;
13
+ }>[];
14
+ staticRemotesIter: AsyncGenerator<{
15
+ success: boolean;
16
+ baseUrl: string;
17
+ }, {
18
+ success: boolean;
19
+ }, unknown> | AsyncGenerator<{
20
+ success: boolean;
21
+ baseUrl: string;
22
+ } | {
23
+ success: boolean;
24
+ }, void, unknown>;
25
+ }>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startRemoteIterators = startRemoteIterators;
4
+ const utils_1 = require("../../utils");
5
+ const build_static_remotes_1 = require("./build-static-remotes");
6
+ const start_static_remotes_file_server_1 = require("./start-static-remotes-file-server");
7
+ const devkit_1 = require("@nx/devkit");
8
+ async function startRemoteIterators(options, context, startRemoteFn, pathToManifestFile, pluginName = 'react', isServer = false) {
9
+ const nxBin = require.resolve('nx/bin/nx');
10
+ const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(context.projectGraph);
11
+ const project = workspaceProjects[context.projectName];
12
+ const moduleFederationConfig = (0, utils_1.getModuleFederationConfig)(project.targets.build.options.tsConfig, context.root, project.root, pluginName);
13
+ const remoteNames = options.devRemotes.map((r) => typeof r === 'string' ? r : r.remoteName);
14
+ const remotes = (0, utils_1.getRemotes)(remoteNames, options.skipRemotes, moduleFederationConfig, {
15
+ projectName: project.name,
16
+ projectGraph: context.projectGraph,
17
+ root: context.root,
18
+ }, pathToManifestFile);
19
+ options.staticRemotesPort ??= remotes.staticRemotePort;
20
+ // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
21
+ process.env.NX_MF_DEV_REMOTES = JSON.stringify([
22
+ ...(remotes.devRemotes.map((r) => typeof r === 'string' ? r : r.remoteName) ?? []).map((r) => r.replace(/-/g, '_')),
23
+ project.name.replace(/-/g, '_'),
24
+ ]);
25
+ const staticRemotesConfig = isServer
26
+ ? (0, utils_1.parseStaticSsrRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context)
27
+ : (0, utils_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
28
+ const mappedLocationsOfStaticRemotes = await (0, build_static_remotes_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options, isServer ? 'server' : 'build');
29
+ const devRemoteIters = await startRemoteFn(remotes.devRemotes, workspaceProjects, options, context, 'serve');
30
+ const staticRemotesIter = isServer
31
+ ? (0, start_static_remotes_file_server_1.startSsrStaticRemotesFileServer)(staticRemotesConfig, context, options)
32
+ : (0, start_static_remotes_file_server_1.startStaticRemotesFileServer)(staticRemotesConfig, context, options);
33
+ isServer
34
+ ? (0, utils_1.startSsrRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes, options.ssl
35
+ ? {
36
+ pathToCert: options.sslCert,
37
+ pathToKey: options.sslKey,
38
+ }
39
+ : undefined)
40
+ : (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes, options.ssl
41
+ ? {
42
+ pathToCert: options.sslCert,
43
+ pathToKey: options.sslKey,
44
+ }
45
+ : undefined);
46
+ return {
47
+ remotes,
48
+ devRemoteIters,
49
+ staticRemotesIter,
50
+ };
51
+ }
@@ -0,0 +1,15 @@
1
+ import { type ExecutorContext } from '@nx/devkit';
2
+ import { type StaticRemotesOptions } from './models';
3
+ import type { StaticRemotesConfig } from '../../utils';
4
+ export declare function startStaticRemotesFileServer(staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, options: StaticRemotesOptions, forceMoveToCommonLocation?: boolean): AsyncGenerator<{
5
+ success: boolean;
6
+ baseUrl: string;
7
+ }, {
8
+ success: boolean;
9
+ }, unknown>;
10
+ export declare function startSsrStaticRemotesFileServer(staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, options: StaticRemotesOptions): AsyncGenerator<{
11
+ success: boolean;
12
+ baseUrl: string;
13
+ } | {
14
+ success: boolean;
15
+ }, void, unknown>;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startStaticRemotesFileServer = startStaticRemotesFileServer;
4
+ exports.startSsrStaticRemotesFileServer = startSsrStaticRemotesFileServer;
5
+ const devkit_1 = require("@nx/devkit");
6
+ const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-server.impl");
7
+ const path_1 = require("path");
8
+ const fs_1 = require("fs");
9
+ function startStaticRemotesFileServer(staticRemotesConfig, context, options, forceMoveToCommonLocation = false) {
10
+ if (!staticRemotesConfig.remotes ||
11
+ staticRemotesConfig.remotes.length === 0) {
12
+ return;
13
+ }
14
+ let shouldMoveToCommonLocation = forceMoveToCommonLocation || false;
15
+ let commonOutputDirectory;
16
+ if (!forceMoveToCommonLocation) {
17
+ for (const app of staticRemotesConfig.remotes) {
18
+ const remoteBasePath = staticRemotesConfig.config[app].basePath;
19
+ if (!commonOutputDirectory) {
20
+ commonOutputDirectory = remoteBasePath;
21
+ }
22
+ else if (commonOutputDirectory !== remoteBasePath) {
23
+ shouldMoveToCommonLocation = true;
24
+ break;
25
+ }
26
+ }
27
+ }
28
+ if (shouldMoveToCommonLocation) {
29
+ commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
30
+ for (const app of staticRemotesConfig.remotes) {
31
+ const remoteConfig = staticRemotesConfig.config[app];
32
+ (0, fs_1.cpSync)(remoteConfig.outputPath, (0, path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
33
+ force: true,
34
+ recursive: true,
35
+ });
36
+ }
37
+ }
38
+ const staticRemotesIter = (0, file_server_impl_1.default)({
39
+ cors: true,
40
+ watch: false,
41
+ staticFilePath: commonOutputDirectory,
42
+ parallel: false,
43
+ spa: false,
44
+ withDeps: false,
45
+ host: options.host,
46
+ port: options.staticRemotesPort,
47
+ ssl: options.ssl,
48
+ sslCert: options.sslCert,
49
+ sslKey: options.sslKey,
50
+ cacheSeconds: -1,
51
+ }, context);
52
+ return staticRemotesIter;
53
+ }
54
+ async function* startSsrStaticRemotesFileServer(staticRemotesConfig, context, options) {
55
+ const staticRemotesIter = startStaticRemotesFileServer(staticRemotesConfig, context, options, true);
56
+ if (!staticRemotesIter) {
57
+ yield { success: true };
58
+ return;
59
+ }
60
+ yield* staticRemotesIter;
61
+ }