@nx/react 23.2.0-pr.36527.2252709 → 23.2.0-pr.36838.ef8e258

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.
Files changed (31) hide show
  1. package/README.md +2 -2
  2. package/dist/src/generators/application/lib/add-e2e.js +6 -6
  3. package/dist/src/generators/application/lib/add-project.js +6 -0
  4. package/dist/src/generators/application/lib/bundlers/add-rsbuild.js +1 -1
  5. package/dist/src/generators/application/lib/create-application-files.js +5 -2
  6. package/dist/src/generators/application/lib/normalize-options.js +3 -2
  7. package/dist/src/generators/application/schema.d.ts +1 -0
  8. package/dist/src/generators/application/schema.json +1 -3
  9. package/dist/src/generators/federate-module/schema.json +1 -1
  10. package/dist/src/generators/host/files/rspack-module-federation/rspack.config.js__tmpl__ +1 -1
  11. package/dist/src/generators/host/files/rspack-module-federation/rspack.config.prod.js__tmpl__ +1 -1
  12. package/dist/src/generators/host/files/rspack-module-federation-ssr/rspack.config.js__tmpl__ +1 -1
  13. package/dist/src/generators/host/files/rspack-module-federation-ssr-ts/rspack.config.ts__tmpl__ +1 -1
  14. package/dist/src/generators/host/files/rspack-module-federation-ts/rspack.config.prod.ts__tmpl__ +1 -1
  15. package/dist/src/generators/host/files/rspack-module-federation-ts/rspack.config.ts__tmpl__ +1 -1
  16. package/dist/src/generators/host/host.js +6 -3
  17. package/dist/src/generators/host/lib/setup-ssr-for-host.js +2 -2
  18. package/dist/src/generators/host/lib/update-module-federation-e2e-project.js +1 -1
  19. package/dist/src/generators/host/schema.d.ts +2 -0
  20. package/dist/src/generators/host/schema.json +4 -4
  21. package/dist/src/generators/remote/files/rspack-module-federation/rspack.config.js__tmpl__ +1 -1
  22. package/dist/src/generators/remote/files/rspack-module-federation-ssr/rspack.config.js__tmpl__ +1 -1
  23. package/dist/src/generators/remote/files/rspack-module-federation-ssr-ts/rspack.config.ts__tmpl__ +1 -1
  24. package/dist/src/generators/remote/files/rspack-module-federation-ts/rspack.config.ts__tmpl__ +1 -1
  25. package/dist/src/generators/remote/lib/setup-ssr-for-remote.js +3 -3
  26. package/dist/src/generators/remote/remote.js +7 -2
  27. package/dist/src/generators/remote/schema.d.ts +2 -0
  28. package/dist/src/generators/remote/schema.json +4 -3
  29. package/dist/src/rules/update-module-federation-project.d.ts +1 -1
  30. package/dist/src/rules/update-module-federation-project.js +5 -5
  31. package/package.json +17 -17
package/README.md CHANGED
@@ -7,9 +7,9 @@
7
7
 
8
8
  <div style="text-align: center;">
9
9
 
10
- [![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)]()
10
+ [![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)](<>)
11
11
  [![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
12
- [![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)]()
12
+ [![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](<>)
13
13
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
14
14
  [![Join us on the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
15
15
  [![Nx Sandboxing](https://staging.nx.app/workspaces/62d013ea0852fe0a2df74438/sandbox-badge.svg)](https://nx.dev/docs/features/ci-features/sandboxing)
@@ -16,7 +16,7 @@ async function addE2e(tree, options) {
16
16
  (await (0, has_rsbuild_plugin_1.hasRsbuildPlugin)(tree, options.appProjectRoot))) ||
17
17
  (options.bundler === 'vite' && (0, has_vite_plugin_1.hasVitePlugin)(tree));
18
18
  let e2eWebServerInfo = {
19
- e2eWebServerAddress: `http://localhost:${options.devServerPort ?? 4200}`,
19
+ e2eWebServerAddress: `http://localhost:${options.port ?? 4200}`,
20
20
  e2eWebServerCommand: `${(0, devkit_1.getPackageManagerCommand)().exec} nx run ${options.projectName}:serve`,
21
21
  e2eCiWebServerCommand: `${(0, devkit_1.getPackageManagerCommand)().exec} nx run ${options.projectName}:serve-static`,
22
22
  e2eCiBaseUrl: `http://localhost:${options.port ?? 4200}`,
@@ -24,26 +24,26 @@ async function addE2e(tree, options) {
24
24
  };
25
25
  if (options.bundler === 'webpack') {
26
26
  const { getWebpackE2EWebServerInfo } = (0, devkit_1.ensurePackage)('@nx/webpack', versions_1.nxVersion);
27
- e2eWebServerInfo = await getWebpackE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `webpack.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.devServerPort ?? 4200);
27
+ e2eWebServerInfo = await getWebpackE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `webpack.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.port);
28
28
  }
29
29
  else if (options.bundler === 'rspack') {
30
30
  const { getRspackE2EWebServerInfo } = (0, devkit_1.ensurePackage)('@nx/rspack', versions_1.nxVersion);
31
- e2eWebServerInfo = await getRspackE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `rspack.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.devServerPort ?? 4200);
31
+ e2eWebServerInfo = await getRspackE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `rspack.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.port);
32
32
  }
33
33
  else if (options.bundler === 'vite') {
34
34
  const { getViteE2EWebServerInfo, getReactRouterE2EWebServerInfo } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
35
35
  e2eWebServerInfo = options.useReactRouter
36
- ? await getReactRouterE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `vite.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.devServerPort ?? 4200,
36
+ ? await getReactRouterE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `vite.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.port ?? 4200,
37
37
  // If the user manually sets the port, then use it for dev and preview
38
38
  options.port)
39
- : await getViteE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `vite.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.devServerPort ?? 4200,
39
+ : await getViteE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `vite.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.port ?? 4200,
40
40
  // If the user manually sets the port, then use it for dev and preview
41
41
  options.port);
42
42
  }
43
43
  else if (options.bundler === 'rsbuild') {
44
44
  (0, devkit_1.ensurePackage)('@nx/rsbuild', versions_1.nxVersion);
45
45
  const { getRsbuildE2EWebServerInfo, } = require('@nx/rsbuild/config-utils');
46
- e2eWebServerInfo = await getRsbuildE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `rsbuild.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.devServerPort ?? 4200);
46
+ e2eWebServerInfo = await getRsbuildE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, `rsbuild.config.${options.js ? 'js' : 'ts'}`), options.addPlugin, options.port ?? 4200);
47
47
  }
48
48
  if (!hasNxBuildPlugin) {
49
49
  await (0, web_1.webStaticServeGenerator)(tree, {
@@ -126,6 +126,9 @@ function createRspackServeTarget(options) {
126
126
  defaultConfiguration: 'development',
127
127
  options: {
128
128
  buildTarget: `${options.projectName}:build`,
129
+ // @nx/rspack:dev-server defaults to 4200 at runtime, not in its schema, so
130
+ // omitting this is safe but the generated executor docs show no default.
131
+ ...(options.port != null ? { port: options.port } : {}),
129
132
  hmr: true,
130
133
  },
131
134
  configurations: {
@@ -197,6 +200,9 @@ function createServeTarget(options) {
197
200
  defaultConfiguration: 'development',
198
201
  options: {
199
202
  buildTarget: `${options.projectName}:build`,
203
+ // Only when asked: @nx/webpack:dev-server already defaults to 4200, so writing
204
+ // it unrequested would just restate the executor's own default.
205
+ ...(options.port != null ? { port: options.port } : {}),
200
206
  hmr: true,
201
207
  },
202
208
  configurations: {
@@ -27,7 +27,7 @@ async function setupRsbuildConfiguration(tree, options, tasks) {
27
27
  }, `./src/main.tsx`),
28
28
  tsConfig: './tsconfig.app.json',
29
29
  target: 'web',
30
- devServerPort: options.devServerPort ?? 4200,
30
+ devServerPort: options.port ?? 4200,
31
31
  });
32
32
  tasks.push(rsbuildTask);
33
33
  const pathToConfigFile = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'rsbuild.config.ts');
@@ -83,7 +83,10 @@ async function createApplicationFiles(host, options) {
83
83
  else if (options.bundler === 'webpack') {
84
84
  (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/base-webpack'), options.appProjectRoot, {
85
85
  ...templateVariables,
86
- webpackPluginOptions: (0, has_webpack_plugin_1.hasWebpackPlugin)(host)
86
+ // Must match addProject's gate. An app that opts out gets executor targets,
87
+ // so it needs the executor-shaped config too — otherwise the plugin config's
88
+ // devServer.port and the serve target's port both describe the same server.
89
+ webpackPluginOptions: (0, has_webpack_plugin_1.hasWebpackPlugin)(host) && options.addPlugin
87
90
  ? createNxWebpackPluginOptions(options, templateVariables.offsetFromRoot)
88
91
  : null,
89
92
  });
@@ -111,7 +114,7 @@ async function createApplicationFiles(host, options) {
111
114
  else if (options.bundler === 'rspack') {
112
115
  (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/base-rspack'), options.appProjectRoot, {
113
116
  ...templateVariables,
114
- rspackPluginOptions: (0, has_rspack_plugin_1.hasRspackPlugin)(host)
117
+ rspackPluginOptions: (0, has_rspack_plugin_1.hasRspackPlugin)(host) && options.addPlugin
115
118
  ? createNxRspackPluginOptions(options, templateVariables.offsetFromRoot)
116
119
  : null,
117
120
  });
@@ -4,7 +4,6 @@ exports.normalizeOptions = normalizeOptions;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const internal_1 = require("@nx/devkit/internal");
6
6
  const assertion_1 = require("../../../utils/assertion");
7
- const find_free_port_1 = require("./find-free-port");
8
7
  const internal_2 = require("@nx/js/internal");
9
8
  async function normalizeOptions(host, options) {
10
9
  await (0, internal_1.ensureRootProjectName)(options, 'application');
@@ -55,7 +54,9 @@ async function normalizeOptions(host, options) {
55
54
  unitTestRunner: options.unitTestRunner ?? 'jest',
56
55
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
57
56
  inSourceTests: options.minimal || options.inSourceTests,
58
- devServerPort: options.devServerPort ?? options.port ?? (0, find_free_port_1.findFreePort)(host),
57
+ // This generator's CLI option has always been `--port`; `devServerPort` is
58
+ // programmatic-only back-compat, so there is no schema alias to lean on here.
59
+ port: options.port ?? options.devServerPort,
59
60
  minimal: options.minimal ?? false,
60
61
  // Programmatic callers such as the host and remote generators leave this
61
62
  // unset; the guards downstream read an unresolved `undefined` as "not eslint"
@@ -26,6 +26,7 @@ export interface Schema {
26
26
  setParserOptionsProject?: boolean;
27
27
  compiler?: 'babel' | 'swc';
28
28
  remotes?: string[];
29
+ /** @deprecated Use {@link Schema.port} instead. This option will be removed in Nx v25. */
29
30
  devServerPort?: number;
30
31
  skipPackageJson?: boolean;
31
32
  rootProject?: boolean;
@@ -193,9 +193,7 @@
193
193
  },
194
194
  "port": {
195
195
  "type": "number",
196
- "description": "The port to use for the development server",
197
- "x-prompt": "Which port would you like to use for the dev server?",
198
- "default": 4200
196
+ "description": "The port to use for the development server. Defaults to 4200."
199
197
  }
200
198
  },
201
199
  "required": ["directory"],
@@ -62,7 +62,7 @@
62
62
  },
63
63
  "unitTestRunner": {
64
64
  "type": "string",
65
- "enum": ["jest", "none"],
65
+ "enum": ["jest", "vitest", "none"],
66
66
  "description": "Test runner to use for unit tests.",
67
67
  "default": "jest"
68
68
  },
@@ -13,7 +13,7 @@ module.exports = {
13
13
  publicPath: 'auto'
14
14
  },
15
15
  devServer: {
16
- port: <%= devServerPort %>,
16
+ port: <%= port %>,
17
17
  historyApiFallback: {
18
18
  index: '/index.html',
19
19
  disableDotRule: true,
@@ -37,7 +37,7 @@ module.exports = {
37
37
  publicPath: 'auto'
38
38
  },
39
39
  devServer: {
40
- port: <%= devServerPort %>,
40
+ port: <%= port %>,
41
41
  historyApiFallback: {
42
42
  index: '/index.html',
43
43
  disableDotRule: true,
@@ -15,7 +15,7 @@ const browserRspackConfig = {
15
15
  publicPath: 'auto'
16
16
  },
17
17
  devServer: {
18
- port: <%= devServerPort %>,
18
+ port: <%= port %>,
19
19
  historyApiFallback: {
20
20
  index: '/index.html',
21
21
  disableDotRule: true,
@@ -15,7 +15,7 @@ const browserRspackConfig = {
15
15
  publicPath: 'auto'
16
16
  },
17
17
  devServer: {
18
- port: <%= devServerPort %>,
18
+ port: <%= port %>,
19
19
  historyApiFallback: {
20
20
  index: '/index.html',
21
21
  disableDotRule: true,
@@ -38,7 +38,7 @@ export default {
38
38
  publicPath: 'auto'
39
39
  },
40
40
  devServer: {
41
- port: <%= devServerPort %>,
41
+ port: <%= port %>,
42
42
  historyApiFallback: {
43
43
  index: '/index.html',
44
44
  disableDotRule: true,
@@ -13,7 +13,7 @@ export default {
13
13
  publicPath: 'auto'
14
14
  },
15
15
  devServer: {
16
- port: <%= devServerPort %>,
16
+ port: <%= port %>,
17
17
  historyApiFallback: {
18
18
  index: '/index.html',
19
19
  disableDotRule: true,
@@ -40,6 +40,9 @@ async function hostGenerator(host, schema) {
40
40
  // TODO(colum): remove when Webpack MF works with Crystal
41
41
  addPlugin: !schema.bundler || schema.bundler === 'rspack' ? true : false,
42
42
  bundler: schema.bundler ?? 'rspack',
43
+ // The schema carries no default, so supply one here: remotes are numbered up
44
+ // from the host's port (`options.port + 1` below), which needs a concrete value.
45
+ port: schema.port ?? schema.devServerPort ?? 4200,
43
46
  };
44
47
  // Check to see if remotes are provided and also check if --dynamic is provided
45
48
  // if both are check that the remotes are valid names else throw an error.
@@ -73,7 +76,7 @@ async function hostGenerator(host, schema) {
73
76
  }
74
77
  const remotesWithPorts = [];
75
78
  if (schema.remotes) {
76
- let remotePort = options.devServerPort + 1;
79
+ let remotePort = options.port + 1;
77
80
  for (const remote of schema.remotes) {
78
81
  const remoteName = await (0, normalize_remote_1.normalizeRemoteName)(host, remote, options);
79
82
  remotesWithPorts.push({ name: remoteName, port: remotePort });
@@ -84,7 +87,7 @@ async function hostGenerator(host, schema) {
84
87
  unitTestRunner: options.unitTestRunner,
85
88
  e2eTestRunner: options.e2eTestRunner,
86
89
  linter: options.linter,
87
- devServerPort: remotePort,
90
+ port: remotePort,
88
91
  ssr: options.ssr,
89
92
  skipFormat: true,
90
93
  typescriptConfiguration: options.typescriptConfiguration,
@@ -110,7 +113,7 @@ async function hostGenerator(host, schema) {
110
113
  if (options.bundler !== 'rspack') {
111
114
  const setupSsrTask = await (0, setup_ssr_1.default)(host, {
112
115
  project: options.projectName,
113
- serverPort: options.devServerPort,
116
+ serverPort: options.port,
114
117
  skipFormat: true,
115
118
  });
116
119
  tasks.push(setupSsrTask);
@@ -22,7 +22,7 @@ async function setupSsrForHost(tree, options, appName, defaultRemoteManifest) {
22
22
  ...(0, create_application_files_1.createNxRspackPluginOptions)(options, (0, devkit_1.offsetFromRoot)(options.appProjectRoot), false),
23
23
  mainServer: `./server.ts`,
24
24
  },
25
- port: Number(options?.devServerPort) || 4200,
25
+ port: Number(options?.port) || 4200,
26
26
  appName,
27
27
  static: !options?.dynamic,
28
28
  remotes: defaultRemoteManifest.map(({ name, port }) => {
@@ -35,7 +35,7 @@ async function setupSsrForHost(tree, options, appName, defaultRemoteManifest) {
35
35
  : {
36
36
  ...options,
37
37
  static: !options?.dynamic,
38
- port: Number(options?.devServerPort) || 4200,
38
+ port: Number(options?.port) || 4200,
39
39
  appName,
40
40
  tmpl: '',
41
41
  browserBuildOutputPath: project.targets.build?.options?.outputPath,
@@ -8,7 +8,7 @@ function updateModuleFederationE2eProject(host, options) {
8
8
  if (projectConfig.targets.e2e.executor !== '@nx/playwright:playwright') {
9
9
  projectConfig.targets.e2e.options = {
10
10
  ...projectConfig.targets.e2e.options,
11
- baseUrl: `http://localhost:${options.devServerPort}`,
11
+ baseUrl: `http://localhost:${options.port}`,
12
12
  };
13
13
  (0, devkit_1.updateProjectConfiguration)(host, options.e2eProjectName, projectConfig);
14
14
  }
@@ -4,6 +4,8 @@ import type { SupportedStyles } from '../../../typings/style';
4
4
  export interface Schema {
5
5
  classComponent?: boolean;
6
6
  compiler?: 'babel' | 'swc';
7
+ port?: number;
8
+ /** @deprecated Use {@link Schema.port} instead. This option will be removed in Nx v24. */
7
9
  devServerPort?: number;
8
10
  directory: string;
9
11
  e2eTestRunner: 'cypress' | 'playwright' | 'none';
@@ -71,7 +71,7 @@
71
71
  },
72
72
  "unitTestRunner": {
73
73
  "type": "string",
74
- "enum": ["jest", "none"],
74
+ "enum": ["jest", "vitest", "none"],
75
75
  "description": "Test runner to use for unit tests.",
76
76
  "default": "jest"
77
77
  },
@@ -132,10 +132,10 @@
132
132
  "x-priority": "important",
133
133
  "alias": "producers"
134
134
  },
135
- "devServerPort": {
135
+ "port": {
136
136
  "type": "number",
137
- "description": "The port for the dev server of the Producer (remote) app.",
138
- "default": 4200,
137
+ "description": "The port at which the Consumer (host) application should be served. Defaults to 4200.",
138
+ "aliases": ["devServerPort"],
139
139
  "x-priority": "important"
140
140
  },
141
141
  "ssr": {
@@ -13,7 +13,7 @@ module.exports = {
13
13
  publicPath: 'auto'
14
14
  },
15
15
  devServer: {
16
- port: <%= devServerPort %>,
16
+ port: <%= port %>,
17
17
  headers: {
18
18
  "Access-Control-Allow-Origin": "*"
19
19
  },
@@ -15,7 +15,7 @@ const browserRspackConfig = {
15
15
  publicPath: 'auto'
16
16
  },
17
17
  devServer: {
18
- port: <%= devServerPort %>,
18
+ port: <%= port %>,
19
19
  headers: {
20
20
  "Access-Control-Allow-Origin": "*"
21
21
  },
@@ -15,7 +15,7 @@ const browserRspackConfig = {
15
15
  publicPath: 'auto'
16
16
  },
17
17
  devServer: {
18
- port: <%= devServerPort %>,
18
+ port: <%= port %>,
19
19
  headers: {
20
20
  "Access-Control-Allow-Origin": "*"
21
21
  },
@@ -13,7 +13,7 @@ export default {
13
13
  publicPath: 'auto'
14
14
  },
15
15
  devServer: {
16
- port: <%= devServerPort %>,
16
+ port: <%= port %>,
17
17
  headers: {
18
18
  "Access-Control-Allow-Origin": "*"
19
19
  },
@@ -17,12 +17,12 @@ async function setupSsrForRemote(tree, options, appName) {
17
17
  ...(0, create_application_files_1.createNxRspackPluginOptions)(options, (0, devkit_1.offsetFromRoot)(options.appProjectRoot), false),
18
18
  mainServer: `./server.ts`,
19
19
  },
20
- port: Number(options?.devServerPort) || 4200,
20
+ port: Number(options?.port) || 4200,
21
21
  appName,
22
22
  }
23
23
  : {
24
24
  ...options,
25
- port: Number(options?.devServerPort) || 4200,
25
+ port: Number(options?.port) || 4200,
26
26
  appName,
27
27
  tmpl: '',
28
28
  browserBuildOutputPath: project.targets.build?.options?.outputPath,
@@ -45,7 +45,7 @@ async function setupSsrForRemote(tree, options, appName) {
45
45
  executor: 'nx:run-commands',
46
46
  defaultConfiguration: 'development',
47
47
  options: {
48
- command: `PORT=${options.devServerPort ?? 4200} node ${(0, devkit_1.joinPathFragments)(serverOutputPath, serverOutputName)}`,
48
+ command: `PORT=${options.port ?? 4200} node ${(0, devkit_1.joinPathFragments)(serverOutputPath, serverOutputName)}`,
49
49
  },
50
50
  };
51
51
  (0, devkit_1.updateProjectConfiguration)(tree, appName, project);
@@ -13,6 +13,7 @@ const internal_3 = require("@nx/js/internal");
13
13
  const update_module_federation_project_1 = require("../../rules/update-module-federation-project");
14
14
  const add_mf_env_to_inputs_1 = require("../../utils/add-mf-env-to-inputs");
15
15
  const normalize_remote_1 = require("../../utils/normalize-remote");
16
+ const find_free_port_1 = require("../application/lib/find-free-port");
16
17
  const maybe_js_1 = require("../../utils/maybe-js");
17
18
  const module_federation_deprecation_1 = require("../../utils/module-federation-deprecation");
18
19
  const versions_1 = require("../../utils/versions");
@@ -89,6 +90,10 @@ async function remoteGenerator(host, schema) {
89
90
  // TODO(colum): remove when Webpack MF works with Crystal
90
91
  addPlugin: !schema.bundler || schema.bundler === 'rspack' ? true : false,
91
92
  bundler: schema.bundler ?? 'rspack',
93
+ // Unlike a plain app, a remote needs a port of its own: updateModuleFederationProject
94
+ // writes it to the serve target, and a dynamic remote's is also recorded in the host
95
+ // manifest. findFreePort reads the ports already claimed, so remotes step past each other.
96
+ port: schema.port ?? schema.devServerPort ?? (0, find_free_port_1.findFreePort)(host),
92
97
  };
93
98
  if (options.dynamic) {
94
99
  // Dynamic remotes generate with library { type: 'var' } by default.
@@ -139,7 +144,7 @@ async function remoteGenerator(host, schema) {
139
144
  if (options.bundler !== 'rspack') {
140
145
  const setupSsrTask = await (0, setup_ssr_1.default)(host, {
141
146
  project: options.projectName,
142
- serverPort: options.devServerPort,
147
+ serverPort: options.port,
143
148
  skipFormat: true,
144
149
  bundler: options.bundler,
145
150
  });
@@ -166,7 +171,7 @@ async function remoteGenerator(host, schema) {
166
171
  if (options.host && options.dynamic) {
167
172
  const hostConfig = (0, devkit_1.readProjectConfiguration)(host, schema.host);
168
173
  const pathToMFManifest = (0, devkit_1.joinPathFragments)((0, internal_3.getProjectSourceRoot)(hostConfig, host), 'assets/module-federation.manifest.json');
169
- (0, add_remote_to_dynamic_host_1.addRemoteToDynamicHost)(host, options.projectName, options.devServerPort, pathToMFManifest);
174
+ (0, add_remote_to_dynamic_host_1.addRemoteToDynamicHost)(host, options.projectName, options.port, pathToMFManifest);
170
175
  }
171
176
  (0, add_mf_env_to_inputs_1.addMfEnvToTargetDefaultInputs)(host, options.bundler);
172
177
  const installTask = (0, devkit_1.addDependenciesToPackageJson)(host, {}, {
@@ -5,6 +5,8 @@ import type { NormalizedSchema as ApplicationNormalizedSchema } from '../applica
5
5
  export interface Schema {
6
6
  classComponent?: boolean;
7
7
  compiler?: 'babel' | 'swc';
8
+ port?: number;
9
+ /** @deprecated Use {@link Schema.port} instead. This option will be removed in Nx v24. */
8
10
  devServerPort?: number;
9
11
  directory: string;
10
12
  e2eTestRunner: 'cypress' | 'playwright' | 'none';
@@ -77,7 +77,7 @@
77
77
  },
78
78
  "unitTestRunner": {
79
79
  "type": "string",
80
- "enum": ["jest", "none"],
80
+ "enum": ["jest", "vitest", "none"],
81
81
  "description": "Test runner to use for unit tests.",
82
82
  "default": "jest"
83
83
  },
@@ -137,9 +137,10 @@
137
137
  "x-priority": "important",
138
138
  "alias": "consumer"
139
139
  },
140
- "devServerPort": {
140
+ "port": {
141
141
  "type": "number",
142
- "description": "The port for the dev server of the Producer (remote) app.",
142
+ "description": "The port on which this Producer (remote) app should be served.",
143
+ "aliases": ["devServerPort"],
143
144
  "x-priority": "important"
144
145
  },
145
146
  "ssr": {
@@ -3,7 +3,7 @@ export declare function updateModuleFederationProject(host: Tree, options: {
3
3
  js?: boolean;
4
4
  projectName: string;
5
5
  appProjectRoot: string;
6
- devServerPort?: number;
6
+ port?: number;
7
7
  typescriptConfiguration?: boolean;
8
8
  dynamic?: boolean;
9
9
  bundler?: 'rspack' | 'webpack';
@@ -32,16 +32,16 @@ function updateModuleFederationProject(host, options, isHost = false) {
32
32
  ?.webpackConfig;
33
33
  }
34
34
  }
35
+ // Must precede the executor assignment below, which dereferences targets.serve:
36
+ // a plugin-driven workspace has no serve target in project.json to inherit.
37
+ projectConfig.targets.serve ??= {};
38
+ projectConfig.targets.serve.options ??= {};
35
39
  if (options.bundler !== 'rspack') {
36
40
  projectConfig.targets.serve.executor =
37
41
  '@nx/react:module-federation-dev-server';
38
42
  }
39
- projectConfig.targets.serve ??= {};
40
- projectConfig.targets.serve.options ??= {};
41
43
  projectConfig.targets.serve.options.port =
42
- options.bundler === 'rspack' && options.ssr && isHost
43
- ? 4000
44
- : options.devServerPort;
44
+ options.bundler === 'rspack' && options.ssr && isHost ? 4000 : options.port;
45
45
  // `serve-static` for remotes that don't need to be in development mode
46
46
  if (options.bundler !== 'rspack') {
47
47
  const serveStaticExecutor = '@nx/react:module-federation-static-server';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/react",
3
- "version": "23.2.0-pr.36527.2252709",
3
+ "version": "23.2.0-pr.36838.ef8e258",
4
4
  "private": false,
5
5
  "description": "The React plugin for Nx contains executors and generators for managing React applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Vitest, Playwright, Cypress, and Storybook.\n\n- Generators for applications, libraries, components, hooks, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -96,7 +96,7 @@
96
96
  "react-dom": ">=18.0.0 <20.0.0",
97
97
  "express": "^4.21.2",
98
98
  "http-proxy-middleware": "^3.0.7",
99
- "@nx/module-federation": "23.2.0-pr.36527.2252709"
99
+ "@nx/module-federation": "23.2.0-pr.36838.ef8e258"
100
100
  },
101
101
  "peerDependenciesMeta": {
102
102
  "babel-plugin-react-compiler": {
@@ -118,27 +118,27 @@
118
118
  "minimatch": "10.2.5",
119
119
  "tslib": "^2.3.0",
120
120
  "semver": "^7.6.3",
121
- "@nx/devkit": "23.2.0-pr.36527.2252709",
122
- "@nx/js": "23.2.0-pr.36527.2252709",
123
- "@nx/eslint": "23.2.0-pr.36527.2252709",
124
- "@nx/web": "23.2.0-pr.36527.2252709"
121
+ "@nx/devkit": "23.2.0-pr.36838.ef8e258",
122
+ "@nx/js": "23.2.0-pr.36838.ef8e258",
123
+ "@nx/eslint": "23.2.0-pr.36838.ef8e258",
124
+ "@nx/web": "23.2.0-pr.36838.ef8e258"
125
125
  },
126
126
  "devDependencies": {
127
127
  "express": "^4.21.2",
128
128
  "http-proxy-middleware": "^3.0.7",
129
- "@nx/cypress": "23.2.0-pr.36527.2252709",
130
- "@nx/module-federation": "23.2.0-pr.36527.2252709",
131
- "@nx/playwright": "23.2.0-pr.36527.2252709",
132
- "@nx/rollup": "23.2.0-pr.36527.2252709",
133
- "@nx/rsbuild": "23.2.0-pr.36527.2252709",
134
- "@nx/vite": "23.2.0-pr.36527.2252709",
135
- "@nx/vitest": "23.2.0-pr.36527.2252709",
136
- "@nx/webpack": "23.2.0-pr.36527.2252709",
137
- "@nx/storybook": "23.2.0-pr.36527.2252709",
138
- "nx": "23.2.0-pr.36527.2252709"
129
+ "@nx/cypress": "23.2.0-pr.36838.ef8e258",
130
+ "@nx/module-federation": "23.2.0-pr.36838.ef8e258",
131
+ "@nx/playwright": "23.2.0-pr.36838.ef8e258",
132
+ "@nx/rollup": "23.2.0-pr.36838.ef8e258",
133
+ "@nx/rsbuild": "23.2.0-pr.36838.ef8e258",
134
+ "@nx/vite": "23.2.0-pr.36838.ef8e258",
135
+ "@nx/vitest": "23.2.0-pr.36838.ef8e258",
136
+ "@nx/webpack": "23.2.0-pr.36838.ef8e258",
137
+ "@nx/storybook": "23.2.0-pr.36838.ef8e258",
138
+ "nx": "23.2.0-pr.36838.ef8e258"
139
139
  },
140
140
  "optionalDependencies": {
141
- "@nx/vite": "23.2.0-pr.36527.2252709"
141
+ "@nx/vite": "23.2.0-pr.36838.ef8e258"
142
142
  },
143
143
  "publishConfig": {
144
144
  "access": "public"