@nx/module-federation 21.1.2 → 21.2.0-beta.2
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 +4 -4
- package/angular.d.ts +3 -0
- package/angular.js +3 -0
- package/package.json +4 -4
- package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin.d.ts +13 -0
- package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin.js +72 -0
- package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin.d.ts +11 -0
- package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin.js +70 -0
- package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin.d.ts +15 -0
- package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin.js +107 -0
- package/src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin.js +1 -1
- package/src/plugins/utils/build-static-remotes.js +1 -1
- package/src/plugins/utils/get-static-remotes.d.ts +1 -1
- package/src/plugins/utils/get-static-remotes.js +2 -1
- package/src/utils/remotes.js +22 -26
- package/src/with-module-federation/angular/utils.d.ts +12 -2
- package/src/with-module-federation/angular/utils.js +55 -4
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p style="text-align: center;">
|
|
2
2
|
<picture>
|
|
3
3
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
|
|
4
|
-
<img alt="Nx - Smart
|
|
4
|
+
<img alt="Nx - Smart Repos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
|
|
21
21
|
<hr>
|
|
22
22
|
|
|
23
|
-
# Nx: Smart
|
|
23
|
+
# Nx: Smart Repos · Fast Builds
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
An AI-first build platform that connects everything from your editor to CI. Helping you deliver fast, without breaking things.
|
|
26
26
|
|
|
27
27
|
This package is a [Module Federation plugin for Nx](https://nx.dev/nx-api/module-federation).
|
|
28
28
|
Module Federation allows developers to share code between deployed applications easier and makes team collaboration more efficient.
|
|
@@ -66,5 +66,5 @@ npx nx@latest init
|
|
|
66
66
|
- [Blog Posts About Nx](https://nx.dev/blog)
|
|
67
67
|
|
|
68
68
|
<p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
|
|
69
|
-
width="100%" alt="Nx - Smart
|
|
69
|
+
width="100%" alt="Nx - Smart Repos · Fast Builds"></a></p>
|
|
70
70
|
|
package/angular.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export * from './src/with-module-federation/angular/with-module-federation';
|
|
2
2
|
export * from './src/with-module-federation/angular/with-module-federation-ssr';
|
|
3
|
+
export * from './src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin';
|
|
4
|
+
export * from './src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin';
|
|
5
|
+
export * from './src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin';
|
package/angular.js
CHANGED
|
@@ -3,3 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./src/with-module-federation/angular/with-module-federation"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./src/with-module-federation/angular/with-module-federation-ssr"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin"), exports);
|
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": "21.
|
|
4
|
+
"version": "21.2.0-beta.2",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"executors": "./executors.json",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"tslib": "^2.3.0",
|
|
28
|
-
"@nx/devkit": "21.
|
|
29
|
-
"@nx/js": "21.
|
|
30
|
-
"@nx/web": "21.
|
|
28
|
+
"@nx/devkit": "21.2.0-beta.2",
|
|
29
|
+
"@nx/js": "21.2.0-beta.2",
|
|
30
|
+
"@nx/web": "21.2.0-beta.2",
|
|
31
31
|
"picocolors": "^1.1.0",
|
|
32
32
|
"webpack": "^5.88.0",
|
|
33
33
|
"@rspack/core": "^1.3.8",
|
package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Compiler, RspackPluginInstance } from '@rspack/core';
|
|
2
|
+
import { ModuleFederationConfig } from '../../../utils/models';
|
|
3
|
+
import { NxModuleFederationDevServerConfig } from '../../models';
|
|
4
|
+
export declare class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
|
|
5
|
+
private _options;
|
|
6
|
+
private nxBin;
|
|
7
|
+
constructor(_options: {
|
|
8
|
+
config: ModuleFederationConfig;
|
|
9
|
+
devServerConfig?: NxModuleFederationDevServerConfig;
|
|
10
|
+
});
|
|
11
|
+
apply(compiler: Compiler): void;
|
|
12
|
+
private setup;
|
|
13
|
+
}
|
package/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NxModuleFederationDevServerPlugin = void 0;
|
|
4
|
+
const core_1 = require("@rspack/core");
|
|
5
|
+
const pc = require("picocolors");
|
|
6
|
+
const devkit_1 = require("@nx/devkit");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
const PLUGIN_NAME = 'NxModuleFederationDevServerPlugin';
|
|
11
|
+
class NxModuleFederationDevServerPlugin {
|
|
12
|
+
constructor(_options) {
|
|
13
|
+
this._options = _options;
|
|
14
|
+
this.nxBin = require.resolve('nx/bin/nx');
|
|
15
|
+
this._options.devServerConfig ??= {
|
|
16
|
+
host: 'localhost',
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
apply(compiler) {
|
|
20
|
+
const isDevServer = process.env['WEBPACK_SERVE'];
|
|
21
|
+
if (!isDevServer) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
|
|
25
|
+
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
|
|
26
|
+
const staticRemotesConfig = await this.setup();
|
|
27
|
+
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
|
|
28
|
+
const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
|
|
29
|
+
(0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
|
|
30
|
+
(0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
|
|
31
|
+
pathToCert: this._options.devServerConfig.sslCert,
|
|
32
|
+
pathToKey: this._options.devServerConfig.sslCert,
|
|
33
|
+
});
|
|
34
|
+
new core_1.DefinePlugin({
|
|
35
|
+
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
|
|
36
|
+
}).apply(compiler);
|
|
37
|
+
callback();
|
|
38
|
+
});
|
|
39
|
+
callback();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async setup() {
|
|
43
|
+
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
|
|
44
|
+
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
|
|
45
|
+
const project = workspaceProjects[this._options.config.name];
|
|
46
|
+
if (!this._options.devServerConfig.pathToManifestFile) {
|
|
47
|
+
this._options.devServerConfig.pathToManifestFile =
|
|
48
|
+
(0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const userPathToManifestFile = (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
|
|
52
|
+
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
|
|
53
|
+
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
|
|
54
|
+
}
|
|
55
|
+
else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
|
|
56
|
+
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
|
|
57
|
+
}
|
|
58
|
+
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
|
|
59
|
+
}
|
|
60
|
+
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
|
|
61
|
+
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
|
|
62
|
+
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph);
|
|
63
|
+
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {}, this._options.devServerConfig?.devRemoteFindOptions, this._options.devServerConfig?.host);
|
|
64
|
+
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
|
|
65
|
+
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
|
|
66
|
+
...(devRemotes.length > 0 ? devRemotes : []),
|
|
67
|
+
project.name,
|
|
68
|
+
]);
|
|
69
|
+
return staticRemotesConfig ?? {};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.NxModuleFederationDevServerPlugin = NxModuleFederationDevServerPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Compiler, RspackPluginInstance } from '@rspack/core';
|
|
2
|
+
import { ModuleFederationConfig, NxModuleFederationConfigOverride } from '../../../utils/models';
|
|
3
|
+
export declare class NxModuleFederationPlugin implements RspackPluginInstance {
|
|
4
|
+
private _options;
|
|
5
|
+
private configOverride?;
|
|
6
|
+
constructor(_options: {
|
|
7
|
+
config: ModuleFederationConfig;
|
|
8
|
+
isServer?: boolean;
|
|
9
|
+
}, configOverride?: NxModuleFederationConfigOverride);
|
|
10
|
+
apply(compiler: Compiler): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NxModuleFederationPlugin = void 0;
|
|
4
|
+
const utils_1 = require("../../../with-module-federation/angular/utils");
|
|
5
|
+
class NxModuleFederationPlugin {
|
|
6
|
+
constructor(_options, configOverride) {
|
|
7
|
+
this._options = _options;
|
|
8
|
+
this.configOverride = configOverride;
|
|
9
|
+
}
|
|
10
|
+
apply(compiler) {
|
|
11
|
+
if (global.NX_GRAPH_CREATION) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// This is required to ensure Module Federation will build the project correctly
|
|
15
|
+
compiler.options.optimization ??= {};
|
|
16
|
+
compiler.options.optimization.runtimeChunk = false;
|
|
17
|
+
compiler.options.output.publicPath = !compiler.options.output.publicPath
|
|
18
|
+
? 'auto'
|
|
19
|
+
: compiler.options.output.publicPath;
|
|
20
|
+
compiler.options.output.uniqueName = this._options.config.name;
|
|
21
|
+
if (compiler.options.output.scriptType === 'module') {
|
|
22
|
+
compiler.options.output.scriptType = undefined;
|
|
23
|
+
compiler.options.output.module = undefined;
|
|
24
|
+
}
|
|
25
|
+
if (this._options.isServer) {
|
|
26
|
+
compiler.options.target = 'async-node';
|
|
27
|
+
compiler.options.output.library ??= {
|
|
28
|
+
type: 'commonjs-module',
|
|
29
|
+
};
|
|
30
|
+
compiler.options.output.library.type = 'commonjs-module';
|
|
31
|
+
}
|
|
32
|
+
const config = (0, utils_1.getModuleFederationConfigSync)(this._options.config, {
|
|
33
|
+
isServer: this._options.isServer,
|
|
34
|
+
}, true);
|
|
35
|
+
const sharedLibraries = config.sharedLibraries;
|
|
36
|
+
const sharedDependencies = config.sharedDependencies;
|
|
37
|
+
const mappedRemotes = config.mappedRemotes;
|
|
38
|
+
const runtimePlugins = [];
|
|
39
|
+
if (this.configOverride?.runtimePlugins) {
|
|
40
|
+
runtimePlugins.push(...(this.configOverride.runtimePlugins ?? []));
|
|
41
|
+
}
|
|
42
|
+
if (this._options.isServer) {
|
|
43
|
+
runtimePlugins.push(require.resolve('@module-federation/node/runtimePlugin'));
|
|
44
|
+
}
|
|
45
|
+
new (require('@module-federation/enhanced/rspack').ModuleFederationPlugin)({
|
|
46
|
+
name: this._options.config.name.replace(/-/g, '_'),
|
|
47
|
+
filename: 'remoteEntry.js',
|
|
48
|
+
exposes: this._options.config.exposes,
|
|
49
|
+
remotes: mappedRemotes,
|
|
50
|
+
shared: {
|
|
51
|
+
...(sharedDependencies ?? {}),
|
|
52
|
+
},
|
|
53
|
+
...(this._options.isServer
|
|
54
|
+
? {
|
|
55
|
+
library: {
|
|
56
|
+
type: 'commonjs-module',
|
|
57
|
+
},
|
|
58
|
+
remoteType: 'script',
|
|
59
|
+
}
|
|
60
|
+
: {}),
|
|
61
|
+
...(this.configOverride ? this.configOverride : {}),
|
|
62
|
+
runtimePlugins,
|
|
63
|
+
virtualRuntimeEntry: true,
|
|
64
|
+
}).apply(compiler);
|
|
65
|
+
if (sharedLibraries) {
|
|
66
|
+
sharedLibraries.getReplacementPlugin().apply(compiler);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.NxModuleFederationPlugin = NxModuleFederationPlugin;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Compiler, RspackPluginInstance } from '@rspack/core';
|
|
2
|
+
import { ModuleFederationConfig } from '../../../utils/models';
|
|
3
|
+
import { NxModuleFederationDevServerConfig } from '../../models';
|
|
4
|
+
export declare class NxModuleFederationSSRDevServerPlugin implements RspackPluginInstance {
|
|
5
|
+
private _options;
|
|
6
|
+
private devServerProcess;
|
|
7
|
+
private nxBin;
|
|
8
|
+
constructor(_options: {
|
|
9
|
+
config: ModuleFederationConfig;
|
|
10
|
+
devServerConfig?: NxModuleFederationDevServerConfig;
|
|
11
|
+
});
|
|
12
|
+
apply(compiler: Compiler): void;
|
|
13
|
+
private startServer;
|
|
14
|
+
private setup;
|
|
15
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NxModuleFederationSSRDevServerPlugin = void 0;
|
|
4
|
+
const core_1 = require("@rspack/core");
|
|
5
|
+
const pc = require("picocolors");
|
|
6
|
+
const devkit_1 = require("@nx/devkit");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
const node_child_process_1 = require("node:child_process");
|
|
11
|
+
const PLUGIN_NAME = 'NxModuleFederationSSRDevServerPlugin';
|
|
12
|
+
class NxModuleFederationSSRDevServerPlugin {
|
|
13
|
+
constructor(_options) {
|
|
14
|
+
this._options = _options;
|
|
15
|
+
this.nxBin = require.resolve('nx/bin/nx');
|
|
16
|
+
this._options.devServerConfig ??= {
|
|
17
|
+
host: 'localhost',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
apply(compiler) {
|
|
21
|
+
const isDevServer = process.env['WEBPACK_SERVE'];
|
|
22
|
+
if (!isDevServer) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
|
|
26
|
+
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
|
|
27
|
+
const staticRemotesConfig = await this.setup(compiler);
|
|
28
|
+
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
|
|
29
|
+
const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
|
|
30
|
+
(0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
|
|
31
|
+
(0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
|
|
32
|
+
pathToCert: this._options.devServerConfig.sslCert,
|
|
33
|
+
pathToKey: this._options.devServerConfig.sslCert,
|
|
34
|
+
}, true);
|
|
35
|
+
new core_1.DefinePlugin({
|
|
36
|
+
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
|
|
37
|
+
}).apply(compiler);
|
|
38
|
+
await this.startServer(compiler);
|
|
39
|
+
callback();
|
|
40
|
+
});
|
|
41
|
+
callback();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async startServer(compiler) {
|
|
45
|
+
compiler.hooks.done.tapAsync(PLUGIN_NAME, async (_, callback) => {
|
|
46
|
+
const serverPath = (0, path_1.join)(compiler.options.output.path, compiler.options.output.filename ?? 'server.js');
|
|
47
|
+
if (this.devServerProcess) {
|
|
48
|
+
await new Promise((res) => {
|
|
49
|
+
this.devServerProcess.on('exit', () => {
|
|
50
|
+
res();
|
|
51
|
+
});
|
|
52
|
+
this.devServerProcess.kill('SIGKILL');
|
|
53
|
+
this.devServerProcess = undefined;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (!(0, fs_1.existsSync)(serverPath)) {
|
|
57
|
+
for (let retries = 0; retries < 10; retries++) {
|
|
58
|
+
await new Promise((res) => setTimeout(res, 200));
|
|
59
|
+
if ((0, fs_1.existsSync)(serverPath)) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!(0, fs_1.existsSync)(serverPath)) {
|
|
64
|
+
throw new Error(`Could not find server bundle at ${serverPath}.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
this.devServerProcess = (0, node_child_process_1.fork)(serverPath);
|
|
68
|
+
process.on('exit', () => {
|
|
69
|
+
this.devServerProcess?.kill('SIGKILL');
|
|
70
|
+
});
|
|
71
|
+
process.on('SIGINT', () => {
|
|
72
|
+
this.devServerProcess?.kill('SIGKILL');
|
|
73
|
+
});
|
|
74
|
+
callback();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async setup(compiler) {
|
|
78
|
+
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
|
|
79
|
+
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
|
|
80
|
+
const project = workspaceProjects[this._options.config.name];
|
|
81
|
+
if (!this._options.devServerConfig.pathToManifestFile) {
|
|
82
|
+
this._options.devServerConfig.pathToManifestFile =
|
|
83
|
+
(0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const userPathToManifestFile = (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
|
|
87
|
+
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
|
|
88
|
+
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
|
|
89
|
+
}
|
|
90
|
+
else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
|
|
91
|
+
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
|
|
92
|
+
}
|
|
93
|
+
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
|
|
94
|
+
}
|
|
95
|
+
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
|
|
96
|
+
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
|
|
97
|
+
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph, true);
|
|
98
|
+
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {});
|
|
99
|
+
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
|
|
100
|
+
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
|
|
101
|
+
...(devRemotes.length > 0 ? devRemotes : []),
|
|
102
|
+
project.name,
|
|
103
|
+
]);
|
|
104
|
+
return staticRemotesConfig ?? {};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.NxModuleFederationSSRDevServerPlugin = NxModuleFederationSSRDevServerPlugin;
|
package/src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin.js
CHANGED
|
@@ -60,7 +60,7 @@ class NxModuleFederationDevServerPlugin {
|
|
|
60
60
|
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
|
|
61
61
|
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
|
|
62
62
|
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph);
|
|
63
|
-
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {});
|
|
63
|
+
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {}, this._options.devServerConfig?.devRemoteFindOptions, this._options.devServerConfig?.host);
|
|
64
64
|
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
|
|
65
65
|
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
|
|
66
66
|
...(devRemotes.length > 0 ? devRemotes : []),
|
|
@@ -13,7 +13,7 @@ async function buildStaticRemotes(staticRemotesConfig, options, nxBin) {
|
|
|
13
13
|
}
|
|
14
14
|
const mappedLocationOfRemotes = {};
|
|
15
15
|
for (const app of remotes) {
|
|
16
|
-
mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig[app].urlSegment}`;
|
|
16
|
+
mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host ?? 'localhost'}:${options.staticRemotesPort}/${staticRemotesConfig[app].urlSegment}`;
|
|
17
17
|
}
|
|
18
18
|
await new Promise((res, rej) => {
|
|
19
19
|
console.log(`NX Building ${remotes.length} static remotes...`);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { StaticRemoteConfig } from '../../utils';
|
|
2
2
|
import { DevRemoteFindOptions } from '../models';
|
|
3
|
-
export declare function getStaticRemotes(remotesConfig: Record<string, StaticRemoteConfig>, devRemoteFindOptions?: DevRemoteFindOptions): Promise<Record<string, StaticRemoteConfig>>;
|
|
3
|
+
export declare function getStaticRemotes(remotesConfig: Record<string, StaticRemoteConfig>, devRemoteFindOptions?: DevRemoteFindOptions, host?: string): Promise<Record<string, StaticRemoteConfig>>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getStaticRemotes = getStaticRemotes;
|
|
4
4
|
const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
|
|
5
|
-
async function getStaticRemotes(remotesConfig, devRemoteFindOptions) {
|
|
5
|
+
async function getStaticRemotes(remotesConfig, devRemoteFindOptions, host = '127.0.0.1') {
|
|
6
6
|
const remotes = Object.keys(remotesConfig);
|
|
7
7
|
const findStaticRemotesPromises = [];
|
|
8
8
|
for (const remote of remotes) {
|
|
@@ -10,6 +10,7 @@ async function getStaticRemotes(remotesConfig, devRemoteFindOptions) {
|
|
|
10
10
|
(0, wait_for_port_open_1.waitForPortOpen)(remotesConfig[remote].port, {
|
|
11
11
|
retries: devRemoteFindOptions?.retries ?? 3,
|
|
12
12
|
retryDelay: devRemoteFindOptions?.retryDelay ?? 1000,
|
|
13
|
+
host,
|
|
13
14
|
}).then((res) => {
|
|
14
15
|
resolve(undefined);
|
|
15
16
|
}, (rej) => {
|
package/src/utils/remotes.js
CHANGED
|
@@ -27,30 +27,22 @@ function mapRemotes(remotes, remoteEntryExt, determineRemoteUrl, isRemoteGlobal
|
|
|
27
27
|
}
|
|
28
28
|
// Helper function to deal with remotes that are arrays
|
|
29
29
|
function handleArrayRemote(remote, remoteEntryExt, isRemoteGlobal) {
|
|
30
|
-
|
|
30
|
+
const [nxRemoteProjectName, remoteLocation] = remote;
|
|
31
31
|
const mfRemoteName = normalizeRemoteName(nxRemoteProjectName);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (['.js', '.mjs', '.json'].includes(remoteLocationExt)) {
|
|
35
|
-
if (isRemoteGlobal && !remoteLocation.startsWith(`${mfRemoteName}@`)) {
|
|
36
|
-
return `${mfRemoteName}@${remoteLocation}`;
|
|
37
|
-
}
|
|
32
|
+
// Remote string starts like "promise new Promise(...)" – return as-is
|
|
33
|
+
if (remoteLocation.startsWith('promise new Promise')) {
|
|
38
34
|
return remoteLocation;
|
|
39
35
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// In that case we should use what the user provides as the remote location
|
|
48
|
-
if (!remoteLocation.startsWith('promise new Promise')) {
|
|
49
|
-
return `${globalPrefix}${baseRemote}/remoteEntry.${remoteEntryExt}`;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
return remoteLocation;
|
|
36
|
+
const resolvedUrl = new URL(remoteLocation);
|
|
37
|
+
const ext = (0, path_1.extname)(resolvedUrl.pathname);
|
|
38
|
+
const needsRemoteEntry = !['.js', '.mjs', '.json'].includes(ext);
|
|
39
|
+
if (needsRemoteEntry) {
|
|
40
|
+
resolvedUrl.pathname = resolvedUrl.pathname.endsWith('/')
|
|
41
|
+
? `${resolvedUrl.pathname}remoteEntry.${remoteEntryExt}`
|
|
42
|
+
: `${resolvedUrl.pathname}/remoteEntry.${remoteEntryExt}`;
|
|
53
43
|
}
|
|
44
|
+
const finalRemoteUrl = resolvedUrl.href;
|
|
45
|
+
return isRemoteGlobal ? `${mfRemoteName}@${finalRemoteUrl}` : finalRemoteUrl;
|
|
54
46
|
}
|
|
55
47
|
// Helper function to deal with remotes that are strings
|
|
56
48
|
function handleStringRemote(nxRemoteProjectName, determineRemoteUrl, isRemoteGlobal) {
|
|
@@ -73,12 +65,16 @@ function mapRemotesForSSR(remotes, remoteEntryExt, determineRemoteUrl) {
|
|
|
73
65
|
if (Array.isArray(remote)) {
|
|
74
66
|
let [nxRemoteProjectName, remoteLocation] = remote;
|
|
75
67
|
const mfRemoteName = normalizeRemoteName(nxRemoteProjectName);
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
68
|
+
const resolvedUrl = new URL(remoteLocation);
|
|
69
|
+
const remoteLocationExt = (0, path_1.extname)(resolvedUrl.pathname);
|
|
70
|
+
const needsRemoteEntry = !['.js', '.mjs', '.json'].includes(remoteLocationExt);
|
|
71
|
+
if (needsRemoteEntry) {
|
|
72
|
+
resolvedUrl.pathname = resolvedUrl.pathname.endsWith('/')
|
|
73
|
+
? `${resolvedUrl.pathname}remoteEntry.${remoteEntryExt}`
|
|
74
|
+
: `${resolvedUrl.pathname}/remoteEntry.${remoteEntryExt}`;
|
|
75
|
+
}
|
|
76
|
+
const finalRemoteUrl = resolvedUrl.href;
|
|
77
|
+
mappedRemotes[mfRemoteName] = `${mfRemoteName}@${finalRemoteUrl}`;
|
|
82
78
|
}
|
|
83
79
|
else if (typeof remote === 'string') {
|
|
84
80
|
const mfRemoteName = normalizeRemoteName(remote);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ModuleFederationConfig, SharedLibraryConfig } from '../../utils';
|
|
2
|
-
export declare function applyDefaultEagerPackages(sharedConfig: Record<string, SharedLibraryConfig
|
|
2
|
+
export declare function applyDefaultEagerPackages(sharedConfig: Record<string, SharedLibraryConfig>, useRspack?: boolean): void;
|
|
3
3
|
export declare const DEFAULT_NPM_PACKAGES_TO_AVOID: string[];
|
|
4
4
|
export declare const DEFAULT_ANGULAR_PACKAGES_TO_SHARE: string[];
|
|
5
|
-
export declare function getFunctionDeterminateRemoteUrl(isServer?: boolean): (remote: string) => string;
|
|
5
|
+
export declare function getFunctionDeterminateRemoteUrl(isServer?: boolean, useRspack?: boolean): (remote: string) => string;
|
|
6
6
|
export declare function getModuleFederationConfig(mfConfig: ModuleFederationConfig, options?: {
|
|
7
7
|
isServer: boolean;
|
|
8
8
|
determineRemoteUrl?: (remote: string) => string;
|
|
@@ -13,3 +13,13 @@ export declare function getModuleFederationConfig(mfConfig: ModuleFederationConf
|
|
|
13
13
|
};
|
|
14
14
|
mappedRemotes: Record<string, string>;
|
|
15
15
|
}>;
|
|
16
|
+
export declare function getModuleFederationConfigSync(mfConfig: ModuleFederationConfig, options?: {
|
|
17
|
+
isServer: boolean;
|
|
18
|
+
determineRemoteUrl?: (remote: string) => string;
|
|
19
|
+
}, useRspack?: boolean): {
|
|
20
|
+
sharedLibraries: import("../../utils").SharedWorkspaceLibraryConfig;
|
|
21
|
+
sharedDependencies: {
|
|
22
|
+
[x: string]: SharedLibraryConfig;
|
|
23
|
+
};
|
|
24
|
+
mappedRemotes: Record<string, string>;
|
|
25
|
+
};
|
|
@@ -4,13 +4,25 @@ exports.DEFAULT_ANGULAR_PACKAGES_TO_SHARE = exports.DEFAULT_NPM_PACKAGES_TO_AVOI
|
|
|
4
4
|
exports.applyDefaultEagerPackages = applyDefaultEagerPackages;
|
|
5
5
|
exports.getFunctionDeterminateRemoteUrl = getFunctionDeterminateRemoteUrl;
|
|
6
6
|
exports.getModuleFederationConfig = getModuleFederationConfig;
|
|
7
|
+
exports.getModuleFederationConfigSync = getModuleFederationConfigSync;
|
|
7
8
|
const utils_1 = require("../../utils");
|
|
8
9
|
const devkit_1 = require("@nx/devkit");
|
|
9
10
|
const project_graph_1 = require("nx/src/project-graph/project-graph");
|
|
10
|
-
function applyDefaultEagerPackages(sharedConfig) {
|
|
11
|
+
function applyDefaultEagerPackages(sharedConfig, useRspack = false) {
|
|
11
12
|
const DEFAULT_PACKAGES_TO_LOAD_EAGERLY = [
|
|
12
13
|
'@angular/localize',
|
|
13
14
|
'@angular/localize/init',
|
|
15
|
+
...(useRspack
|
|
16
|
+
? [
|
|
17
|
+
'@angular/core',
|
|
18
|
+
'@angular/core/primitives/signals',
|
|
19
|
+
'@angular/core/event-dispatch',
|
|
20
|
+
'@angular/core/rxjs-interop',
|
|
21
|
+
'@angular/common',
|
|
22
|
+
'@angular/common/http',
|
|
23
|
+
'@angular/platform-browser',
|
|
24
|
+
]
|
|
25
|
+
: []),
|
|
14
26
|
];
|
|
15
27
|
for (const pkg of DEFAULT_PACKAGES_TO_LOAD_EAGERLY) {
|
|
16
28
|
if (!sharedConfig[pkg]) {
|
|
@@ -23,15 +35,20 @@ exports.DEFAULT_NPM_PACKAGES_TO_AVOID = [
|
|
|
23
35
|
'zone.js',
|
|
24
36
|
'@nx/angular/mf',
|
|
25
37
|
'@nrwl/angular/mf',
|
|
38
|
+
'@nx/angular-rspack',
|
|
26
39
|
];
|
|
27
40
|
exports.DEFAULT_ANGULAR_PACKAGES_TO_SHARE = [
|
|
28
41
|
'@angular/core',
|
|
29
42
|
'@angular/animations',
|
|
30
43
|
'@angular/common',
|
|
31
44
|
];
|
|
32
|
-
function getFunctionDeterminateRemoteUrl(isServer = false) {
|
|
45
|
+
function getFunctionDeterminateRemoteUrl(isServer = false, useRspack = false) {
|
|
33
46
|
const target = 'serve';
|
|
34
|
-
const remoteEntry = isServer
|
|
47
|
+
const remoteEntry = isServer
|
|
48
|
+
? 'server/remoteEntry.js'
|
|
49
|
+
: useRspack
|
|
50
|
+
? 'remoteEntry.js'
|
|
51
|
+
: 'remoteEntry.mjs';
|
|
35
52
|
return function (remote) {
|
|
36
53
|
const mappedStaticRemotesFromEnv = process.env
|
|
37
54
|
.NX_MF_DEV_SERVER_STATIC_REMOTES
|
|
@@ -55,7 +72,7 @@ function getFunctionDeterminateRemoteUrl(isServer = false) {
|
|
|
55
72
|
const host = serveTarget.options?.host ??
|
|
56
73
|
`http${serveTarget.options.ssl ? 's' : ''}://localhost`;
|
|
57
74
|
const port = serveTarget.options?.port ?? 4201;
|
|
58
|
-
return `${host.endsWith('/') ? host.slice(0, -1) : host}:${port}/${remoteEntry}`;
|
|
75
|
+
return `${useRspack ? `${remote}@` : ''}${host.endsWith('/') ? host.slice(0, -1) : host}:${port}/${remoteEntry}`;
|
|
59
76
|
};
|
|
60
77
|
}
|
|
61
78
|
async function getModuleFederationConfig(mfConfig, options = { isServer: false }) {
|
|
@@ -99,3 +116,37 @@ async function getModuleFederationConfig(mfConfig, options = { isServer: false }
|
|
|
99
116
|
: mapRemotesFunction(mfConfig.remotes, 'mjs', determineRemoteUrlFn);
|
|
100
117
|
return { sharedLibraries, sharedDependencies, mappedRemotes };
|
|
101
118
|
}
|
|
119
|
+
function getModuleFederationConfigSync(mfConfig, options = { isServer: false }, useRspack = false) {
|
|
120
|
+
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
|
|
121
|
+
if (!projectGraph.nodes[mfConfig.name]?.data) {
|
|
122
|
+
throw Error(`Cannot find project "${mfConfig.name}". Check that the name is correct in module-federation.config.js`);
|
|
123
|
+
}
|
|
124
|
+
const dependencies = (0, utils_1.getDependentPackagesForProject)(projectGraph, mfConfig.name);
|
|
125
|
+
if (mfConfig.shared) {
|
|
126
|
+
dependencies.workspaceLibraries = dependencies.workspaceLibraries.filter((lib) => mfConfig.shared(lib.importKey, {}) !== false);
|
|
127
|
+
dependencies.npmPackages = dependencies.npmPackages.filter((pkg) => mfConfig.shared(pkg, {}) !== false);
|
|
128
|
+
}
|
|
129
|
+
const sharedLibraries = (0, utils_1.shareWorkspaceLibraries)(dependencies.workspaceLibraries);
|
|
130
|
+
const npmPackages = (0, utils_1.sharePackages)(Array.from(new Set([
|
|
131
|
+
...dependencies.npmPackages.filter((pkg) => !exports.DEFAULT_NPM_PACKAGES_TO_AVOID.includes(pkg)),
|
|
132
|
+
])));
|
|
133
|
+
exports.DEFAULT_NPM_PACKAGES_TO_AVOID.forEach((pkgName) => {
|
|
134
|
+
if (pkgName in npmPackages) {
|
|
135
|
+
delete npmPackages[pkgName];
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
const sharedDependencies = {
|
|
139
|
+
...sharedLibraries.getLibraries(projectGraph.nodes[mfConfig.name].data.root),
|
|
140
|
+
...npmPackages,
|
|
141
|
+
};
|
|
142
|
+
applyDefaultEagerPackages(sharedDependencies, useRspack);
|
|
143
|
+
(0, utils_1.applySharedFunction)(sharedDependencies, mfConfig.shared);
|
|
144
|
+
(0, utils_1.applyAdditionalShared)(sharedDependencies, mfConfig.additionalShared, projectGraph);
|
|
145
|
+
const determineRemoteUrlFn = options.determineRemoteUrl ||
|
|
146
|
+
getFunctionDeterminateRemoteUrl(options.isServer, useRspack);
|
|
147
|
+
const mapRemotesFunction = options.isServer ? utils_1.mapRemotesForSSR : utils_1.mapRemotes;
|
|
148
|
+
const mappedRemotes = !mfConfig.remotes || mfConfig.remotes.length === 0
|
|
149
|
+
? {}
|
|
150
|
+
: mapRemotesFunction(mfConfig.remotes, useRspack ? 'js' : 'mjs', determineRemoteUrlFn);
|
|
151
|
+
return { sharedLibraries, sharedDependencies, mappedRemotes };
|
|
152
|
+
}
|