@nx/module-federation 20.6.2 → 20.6.3

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/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.6.2",
4
+ "version": "20.6.3",
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": "20.6.2",
29
- "@nx/js": "20.6.2",
30
- "@nx/web": "20.6.2",
28
+ "@nx/devkit": "20.6.3",
29
+ "@nx/js": "20.6.3",
30
+ "@nx/web": "20.6.3",
31
31
  "picocolors": "^1.1.0",
32
32
  "webpack": "^5.88.0",
33
33
  "@module-federation/enhanced": "^0.9.0",
package/rspack.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from './src/with-module-federation/rspack/with-module-federation';
2
2
  export * from './src/with-module-federation/rspack/with-module-federation-ssr';
3
3
  export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin';
4
4
  export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin';
5
+ export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-ssr-dev-server-plugin';
package/rspack.js CHANGED
@@ -5,3 +5,4 @@ tslib_1.__exportStar(require("./src/with-module-federation/rspack/with-module-fe
5
5
  tslib_1.__exportStar(require("./src/with-module-federation/rspack/with-module-federation-ssr"), exports);
6
6
  tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin"), exports);
7
7
  tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin"), exports);
8
+ tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-ssr-dev-server-plugin"), exports);
@@ -3,10 +3,11 @@ import { ModuleFederationConfig } from '../../../utils/models';
3
3
  import { NxModuleFederationDevServerConfig } from '../../models';
4
4
  export declare class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
5
5
  private _options;
6
+ private devServerProcess;
6
7
  private nxBin;
7
8
  constructor(_options: {
8
9
  config: ModuleFederationConfig;
9
- devServerConfig: NxModuleFederationDevServerConfig;
10
+ devServerConfig?: NxModuleFederationDevServerConfig;
10
11
  });
11
12
  apply(compiler: Compiler): void;
12
13
  private setup;
@@ -12,10 +12,13 @@ class NxModuleFederationDevServerPlugin {
12
12
  constructor(_options) {
13
13
  this._options = _options;
14
14
  this.nxBin = require.resolve('nx/bin/nx');
15
+ this._options.devServerConfig ??= {
16
+ host: 'localhost',
17
+ };
15
18
  }
16
19
  apply(compiler) {
17
20
  compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
18
- const staticRemotesConfig = await this.setup();
21
+ const staticRemotesConfig = await this.setup(compiler);
19
22
  devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
20
23
  const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
21
24
  (0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
@@ -29,7 +32,7 @@ class NxModuleFederationDevServerPlugin {
29
32
  callback();
30
33
  });
31
34
  }
32
- async setup() {
35
+ async setup(compiler) {
33
36
  const projectGraph = (0, devkit_1.readCachedProjectGraph)();
34
37
  const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
35
38
  const project = workspaceProjects[this._options.config.name];
@@ -7,6 +7,7 @@ export declare class NxModuleFederationPlugin implements RspackPluginInstance {
7
7
  constructor(_options: {
8
8
  config: ModuleFederationConfig;
9
9
  devServerConfig?: NxModuleFederationDevServerConfig;
10
+ isServer?: boolean;
10
11
  }, configOverride?: NxModuleFederationConfigOverride);
11
12
  apply(compiler: Compiler): void;
12
13
  }
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NxModuleFederationPlugin = void 0;
4
4
  const utils_1 = require("../../../with-module-federation/rspack/utils");
5
- const nx_module_federation_dev_server_plugin_1 = require("./nx-module-federation-dev-server-plugin");
6
5
  class NxModuleFederationPlugin {
7
6
  constructor(_options, configOverride) {
8
7
  this._options = _options;
@@ -14,12 +13,27 @@ class NxModuleFederationPlugin {
14
13
  }
15
14
  // This is required to ensure Module Federation will build the project correctly
16
15
  compiler.options.optimization.runtimeChunk = false;
17
- const isDevServer = !!process.env['WEBPACK_SERVE'];
18
- // TODO(colum): Add support for SSR
19
- const config = (0, utils_1.getModuleFederationConfig)(this._options.config);
16
+ compiler.options.output.uniqueName = this._options.config.name;
17
+ if (this._options.isServer) {
18
+ compiler.options.target = 'async-node';
19
+ compiler.options.output.library ??= {
20
+ type: 'commonjs-module',
21
+ };
22
+ compiler.options.output.library.type = 'commonjs-module';
23
+ }
24
+ const config = (0, utils_1.getModuleFederationConfig)(this._options.config, {
25
+ isServer: this._options.isServer,
26
+ });
20
27
  const sharedLibraries = config.sharedLibraries;
21
28
  const sharedDependencies = config.sharedDependencies;
22
29
  const mappedRemotes = config.mappedRemotes;
30
+ const runtimePlugins = [];
31
+ if (this.configOverride?.runtimePlugins) {
32
+ runtimePlugins.push(...(this.configOverride.runtimePlugins ?? []));
33
+ }
34
+ if (this._options.isServer) {
35
+ runtimePlugins.push(require.resolve('@module-federation/node/runtimePlugin'));
36
+ }
23
37
  new (require('@module-federation/enhanced/rspack').ModuleFederationPlugin)({
24
38
  name: this._options.config.name.replace(/-/g, '_'),
25
39
  filename: 'remoteEntry.js',
@@ -28,24 +42,21 @@ class NxModuleFederationPlugin {
28
42
  shared: {
29
43
  ...(sharedDependencies ?? {}),
30
44
  },
45
+ ...(this._options.isServer
46
+ ? {
47
+ library: {
48
+ type: 'commonjs-module',
49
+ },
50
+ remoteType: 'script',
51
+ }
52
+ : {}),
31
53
  ...(this.configOverride ? this.configOverride : {}),
32
- runtimePlugins: this.configOverride
33
- ? this.configOverride.runtimePlugins ?? []
34
- : [],
54
+ runtimePlugins,
35
55
  virtualRuntimeEntry: true,
36
56
  }).apply(compiler);
37
57
  if (sharedLibraries) {
38
58
  sharedLibraries.getReplacementPlugin().apply(compiler);
39
59
  }
40
- if (isDevServer) {
41
- new nx_module_federation_dev_server_plugin_1.NxModuleFederationDevServerPlugin({
42
- config: this._options.config,
43
- devServerConfig: {
44
- ...(this._options.devServerConfig ?? {}),
45
- host: this._options.devServerConfig?.host ?? 'localhost',
46
- },
47
- }).apply(compiler);
48
- }
49
60
  }
50
61
  }
51
62
  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,103 @@
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
+ compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
22
+ compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
23
+ const staticRemotesConfig = await this.setup(compiler);
24
+ devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
25
+ const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
26
+ (0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
27
+ (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
28
+ pathToCert: this._options.devServerConfig.sslCert,
29
+ pathToKey: this._options.devServerConfig.sslCert,
30
+ }, true);
31
+ new core_1.DefinePlugin({
32
+ 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
33
+ }).apply(compiler);
34
+ await this.startServer(compiler);
35
+ callback();
36
+ });
37
+ callback();
38
+ });
39
+ }
40
+ async startServer(compiler) {
41
+ compiler.hooks.afterEmit.tapAsync(PLUGIN_NAME, async (_, callback) => {
42
+ const serverPath = (0, path_1.join)(compiler.options.output.path, compiler.options.output.filename ?? 'server.js');
43
+ if (this.devServerProcess) {
44
+ await new Promise((res) => {
45
+ this.devServerProcess.on('exit', () => {
46
+ res();
47
+ });
48
+ this.devServerProcess.kill();
49
+ this.devServerProcess = undefined;
50
+ });
51
+ }
52
+ if (!(0, fs_1.existsSync)(serverPath)) {
53
+ for (let retries = 0; retries < 10; retries++) {
54
+ await new Promise((res) => setTimeout(res, 100));
55
+ if ((0, fs_1.existsSync)(serverPath)) {
56
+ break;
57
+ }
58
+ }
59
+ if (!(0, fs_1.existsSync)(serverPath)) {
60
+ throw new Error(`Could not find server bundle at ${serverPath}.`);
61
+ }
62
+ }
63
+ this.devServerProcess = (0, node_child_process_1.fork)(serverPath);
64
+ process.on('exit', () => {
65
+ this.devServerProcess?.kill();
66
+ });
67
+ process.on('SIGINT', () => {
68
+ this.devServerProcess?.kill();
69
+ });
70
+ callback();
71
+ });
72
+ }
73
+ async setup(compiler) {
74
+ const projectGraph = (0, devkit_1.readCachedProjectGraph)();
75
+ const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
76
+ const project = workspaceProjects[this._options.config.name];
77
+ if (!this._options.devServerConfig.pathToManifestFile) {
78
+ this._options.devServerConfig.pathToManifestFile =
79
+ (0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
80
+ }
81
+ else {
82
+ const userPathToManifestFile = (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
83
+ if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
84
+ throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
85
+ }
86
+ else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
87
+ throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
88
+ }
89
+ this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
90
+ }
91
+ const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
92
+ this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
93
+ const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph, true);
94
+ const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {});
95
+ const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
96
+ process.env.NX_MF_DEV_REMOTES = JSON.stringify([
97
+ ...(devRemotes.length > 0 ? devRemotes : []),
98
+ project.name,
99
+ ]);
100
+ return staticRemotesConfig ?? {};
101
+ }
102
+ }
103
+ exports.NxModuleFederationSSRDevServerPlugin = NxModuleFederationSSRDevServerPlugin;
@@ -1,6 +1,6 @@
1
1
  import { ProjectGraph } from '@nx/devkit';
2
2
  import { StaticRemoteConfig } from '../../utils';
3
- export declare function parseRemotesConfig(remotes: string[] | undefined, workspaceRoot: string, projectGraph: ProjectGraph): {
3
+ export declare function parseRemotesConfig(remotes: string[] | undefined, workspaceRoot: string, projectGraph: ProjectGraph, isServer?: boolean): {
4
4
  remotes: string[];
5
5
  config: Record<string, StaticRemoteConfig>;
6
6
  };
@@ -4,7 +4,7 @@ exports.parseRemotesConfig = parseRemotesConfig;
4
4
  const path_1 = require("path");
5
5
  const devkit_internals_1 = require("nx/src/devkit-internals");
6
6
  const devkit_1 = require("@nx/devkit");
7
- function parseRemotesConfig(remotes, workspaceRoot, projectGraph) {
7
+ function parseRemotesConfig(remotes, workspaceRoot, projectGraph, isServer) {
8
8
  if (!remotes?.length) {
9
9
  return { remotes: [], config: undefined };
10
10
  }
@@ -24,7 +24,12 @@ function parseRemotesConfig(remotes, workspaceRoot, projectGraph) {
24
24
  const basePath = (0, path_1.dirname)(outputPath);
25
25
  const urlSegment = app;
26
26
  const port = projectGraph.nodes[app].data.targets?.['serve']?.options.port;
27
- config[app] = { basePath, outputPath, urlSegment, port };
27
+ config[app] = {
28
+ basePath,
29
+ outputPath: isServer ? (0, path_1.dirname)(outputPath) : outputPath,
30
+ urlSegment,
31
+ port,
32
+ };
28
33
  }
29
34
  return { remotes, config };
30
35
  }
@@ -2,4 +2,4 @@ import { StaticRemoteConfig } from '../../utils';
2
2
  export declare function startRemoteProxies(staticRemotesConfig: Record<string, StaticRemoteConfig>, mappedLocationsOfRemotes: Record<string, string>, sslOptions?: {
3
3
  pathToCert: string;
4
4
  pathToKey: string;
5
- }): void;
5
+ }, isServer?: boolean): void;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.startRemoteProxies = startRemoteProxies;
4
4
  const fs_1 = require("fs");
5
- function startRemoteProxies(staticRemotesConfig, mappedLocationsOfRemotes, sslOptions) {
5
+ function startRemoteProxies(staticRemotesConfig, mappedLocationsOfRemotes, sslOptions, isServer) {
6
6
  const { createProxyMiddleware } = require('http-proxy-middleware');
7
7
  const express = require('express');
8
8
  let sslCert;
@@ -28,6 +28,16 @@ function startRemoteProxies(staticRemotesConfig, mappedLocationsOfRemotes, sslOp
28
28
  target: mappedLocationsOfRemotes[app],
29
29
  changeOrigin: true,
30
30
  secure: sslCert ? false : undefined,
31
+ pathRewrite: isServer
32
+ ? (path) => {
33
+ if (path.includes('/server')) {
34
+ return path;
35
+ }
36
+ else {
37
+ return `browser/${path}`;
38
+ }
39
+ }
40
+ : undefined,
31
41
  }));
32
42
  const proxyServer = (sslCert ? https : http)
33
43
  .createServer({ cert: sslCert, key: sslKey }, expressProxy)