@nx/react 0.0.0-pr-26891-95f6262 → 0.0.0-pr-26482-1bdb7bd

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.
@@ -1,4 +1,5 @@
1
1
  export type ResolveRemoteUrlFunction = (remoteName: string) => string | Promise<string>;
2
2
  export declare function setRemoteUrlResolver(_resolveRemoteUrl: ResolveRemoteUrlFunction): void;
3
3
  export declare function setRemoteDefinitions(definitions: Record<string, string>): void;
4
+ export declare function setRemoteDefinition(remoteName: string, remoteUrl: string): void;
4
5
  export declare function loadRemoteModule(remoteName: string, moduleName: string): Promise<any>;
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setRemoteUrlResolver = setRemoteUrlResolver;
4
4
  exports.setRemoteDefinitions = setRemoteDefinitions;
5
+ exports.setRemoteDefinition = setRemoteDefinition;
5
6
  exports.loadRemoteModule = loadRemoteModule;
6
- let remoteUrlDefinitions;
7
+ let remoteUrlDefinitions = {};
7
8
  let resolveRemoteUrl;
8
9
  const remoteModuleMap = new Map();
9
10
  const remoteContainerMap = new Map();
@@ -14,6 +15,9 @@ function setRemoteUrlResolver(_resolveRemoteUrl) {
14
15
  function setRemoteDefinitions(definitions) {
15
16
  remoteUrlDefinitions = definitions;
16
17
  }
18
+ function setRemoteDefinition(remoteName, remoteUrl) {
19
+ remoteUrlDefinitions[remoteName] = remoteUrl;
20
+ }
17
21
  async function loadRemoteModule(remoteName, moduleName) {
18
22
  const remoteModuleKey = `${remoteName}:${moduleName}`;
19
23
  if (remoteModuleMap.has(remoteModuleKey)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/react",
3
- "version": "0.0.0-pr-26891-95f6262",
3
+ "version": "0.0.0-pr-26482-1bdb7bd",
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": {
@@ -39,11 +39,11 @@
39
39
  "minimatch": "9.0.3",
40
40
  "tslib": "^2.3.0",
41
41
  "@module-federation/enhanced": "~0.2.3",
42
- "@nx/devkit": "0.0.0-pr-26891-95f6262",
43
- "@nx/js": "0.0.0-pr-26891-95f6262",
44
- "@nx/eslint": "0.0.0-pr-26891-95f6262",
45
- "@nx/web": "0.0.0-pr-26891-95f6262",
46
- "@nrwl/react": "0.0.0-pr-26891-95f6262"
42
+ "@nx/devkit": "0.0.0-pr-26482-1bdb7bd",
43
+ "@nx/js": "0.0.0-pr-26482-1bdb7bd",
44
+ "@nx/eslint": "0.0.0-pr-26482-1bdb7bd",
45
+ "@nx/web": "0.0.0-pr-26482-1bdb7bd",
46
+ "@nrwl/react": "0.0.0-pr-26482-1bdb7bd"
47
47
  },
48
48
  "publishConfig": {
49
49
  "access": "public"
@@ -12,16 +12,6 @@ type ModuleFederationDevServerOptions = WebDevServerOptions & {
12
12
  staticRemotesPort?: number;
13
13
  pathToManifestFile?: string;
14
14
  };
15
- type StaticRemoteConfig = {
16
- basePath: string;
17
- outputPath: string;
18
- urlSegment: string;
19
- };
20
- type StaticRemotesConfig = {
21
- remotes: string[];
22
- config: Record<string, StaticRemoteConfig> | undefined;
23
- };
24
- export declare function parseStaticRemotesConfig(staticRemotes: string[] | undefined, context: ExecutorContext): StaticRemotesConfig;
25
15
  export default function moduleFederationDevServer(options: ModuleFederationDevServerOptions, context: ExecutorContext): AsyncIterableIterator<{
26
16
  success: boolean;
27
17
  baseUrl?: string;
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseStaticRemotesConfig = parseStaticRemotesConfig;
4
3
  exports.default = moduleFederationDevServer;
5
4
  const devkit_1 = require("@nx/devkit");
6
5
  const dev_server_impl_1 = require("@nx/webpack/src/executors/dev-server/dev-server.impl");
@@ -14,6 +13,8 @@ const node_path_1 = require("node:path");
14
13
  const node_fs_1 = require("node:fs");
15
14
  const fs_1 = require("fs");
16
15
  const path_1 = require("path");
16
+ const start_remote_proxies_1 = require("@nx/webpack/src/utils/module-federation/start-remote-proxies");
17
+ const parse_static_remotes_config_1 = require("@nx/webpack/src/utils/module-federation/parse-static-remotes-config");
17
18
  function getBuildOptions(buildTarget, context) {
18
19
  const target = (0, devkit_1.parseTargetString)(buildTarget, context);
19
20
  const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
@@ -22,6 +23,10 @@ function getBuildOptions(buildTarget, context) {
22
23
  };
23
24
  }
24
25
  function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
26
+ if (!staticRemotesConfig.remotes ||
27
+ staticRemotesConfig.remotes.length === 0) {
28
+ return;
29
+ }
25
30
  let shouldMoveToCommonLocation = false;
26
31
  let commonOutputDirectory;
27
32
  for (const app of staticRemotesConfig.remotes) {
@@ -56,6 +61,7 @@ function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
56
61
  ssl: options.ssl,
57
62
  sslCert: options.sslCert,
58
63
  sslKey: options.sslKey,
64
+ cacheSeconds: -1,
59
65
  }, context);
60
66
  return staticRemotesIter;
61
67
  }
@@ -98,7 +104,7 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
98
104
  mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig.config[app].urlSegment}`;
99
105
  }
100
106
  process.env.NX_MF_DEV_SERVER_STATIC_REMOTES = JSON.stringify(mappedLocationOfRemotes);
101
- await new Promise((res) => {
107
+ await new Promise((res, rej) => {
102
108
  const staticProcess = (0, node_child_process_1.fork)(nxBin, [
103
109
  'run-many',
104
110
  `--target=build`,
@@ -118,6 +124,11 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
118
124
  const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
119
125
  const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
120
126
  stdoutStream.write(stdoutString);
127
+ // in addition to writing into the stdout stream, also show error directly in console
128
+ // so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
129
+ if (stdoutString.includes('ERROR in')) {
130
+ devkit_1.logger.log(stdoutString);
131
+ }
121
132
  if (stdoutString.includes('Successfully ran target build')) {
122
133
  staticProcess.stdout.removeAllListeners('data');
123
134
  devkit_1.logger.info(`NX Built ${staticRemotesConfig.remotes.length} static remotes`);
@@ -130,30 +141,18 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
130
141
  staticProcess.stdout.removeAllListeners('data');
131
142
  staticProcess.stderr.removeAllListeners('data');
132
143
  if (code !== 0) {
133
- throw new Error(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
144
+ rej(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
145
+ }
146
+ else {
147
+ res();
134
148
  }
135
- res();
136
149
  });
137
150
  process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
138
151
  process.on('exit', () => staticProcess.kill('SIGTERM'));
139
152
  });
140
- }
141
- function parseStaticRemotesConfig(staticRemotes, context) {
142
- if (!staticRemotes?.length) {
143
- return { remotes: [], config: undefined };
144
- }
145
- const config = {};
146
- for (const app of staticRemotes) {
147
- const outputPath = context.projectGraph.nodes[app].data.targets['build'].options.outputPath;
148
- const basePath = (0, node_path_1.dirname)(outputPath);
149
- const urlSegment = (0, node_path_1.basename)(outputPath);
150
- config[app] = { basePath, outputPath, urlSegment };
151
- }
152
- return { remotes: staticRemotes, config };
153
+ return mappedLocationOfRemotes;
153
154
  }
154
155
  async function* moduleFederationDevServer(options, context) {
155
- const initialStaticRemotesPorts = options.staticRemotesPort;
156
- options.staticRemotesPort ??= options.port + 1;
157
156
  // Force Node to resolve to look for the nx binary that is inside node_modules
158
157
  const nxBin = require.resolve('nx/bin/nx');
159
158
  const currIter = options.static
@@ -163,6 +162,7 @@ async function* moduleFederationDevServer(options, context) {
163
162
  withDeps: false,
164
163
  spa: false,
165
164
  cors: true,
165
+ cacheSeconds: -1,
166
166
  }, context)
167
167
  : (0, dev_server_impl_1.default)(options, context);
168
168
  const p = context.projectsConfigurations.projects[context.projectName];
@@ -188,27 +188,15 @@ async function* moduleFederationDevServer(options, context) {
188
188
  projectGraph: context.projectGraph,
189
189
  root: context.root,
190
190
  }, pathToManifestFile);
191
- if (remotes.devRemotes.length > 0 && !initialStaticRemotesPorts) {
192
- options.staticRemotesPort = options.devRemotes.reduce((portToUse, r) => {
193
- const remoteName = typeof r === 'string' ? r : r.remoteName;
194
- const remotePort = context.projectGraph.nodes[remoteName].data.targets['serve'].options
195
- .port;
196
- if (remotePort >= portToUse) {
197
- return remotePort + 1;
198
- }
199
- else {
200
- return portToUse;
201
- }
202
- }, options.staticRemotesPort);
203
- }
204
- const staticRemotesConfig = parseStaticRemotesConfig(remotes.staticRemotes, context);
205
- await buildStaticRemotes(staticRemotesConfig, nxBin, context, options);
191
+ options.staticRemotesPort ??= remotes.staticRemotePort;
192
+ // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
193
+ process.env.NX_MF_DEV_REMOTES = JSON.stringify(remotes.devRemotes.map((r) => (typeof r === 'string' ? r : r.remoteName)));
194
+ const staticRemotesConfig = (0, parse_static_remotes_config_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
195
+ const mappedLocationsOfStaticRemotes = await buildStaticRemotes(staticRemotesConfig, nxBin, context, options);
206
196
  const devRemoteIters = await startRemotes(remotes.devRemotes, context, options, 'serve');
207
- const dynamicRemotesIters = await startRemotes(remotes.dynamicRemotes, context, options, 'serve-static');
208
- const staticRemotesIter = remotes.staticRemotes.length > 0
209
- ? startStaticRemotesFileServer(staticRemotesConfig, context, options)
210
- : undefined;
211
- return yield* (0, async_iterable_1.combineAsyncIterables)(currIter, ...devRemoteIters, ...dynamicRemotesIters, ...(staticRemotesIter ? [staticRemotesIter] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
197
+ const staticRemotesIter = startStaticRemotesFileServer(staticRemotesConfig, context, options);
198
+ (0, start_remote_proxies_1.startRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes);
199
+ return yield* (0, async_iterable_1.combineAsyncIterables)(currIter, ...devRemoteIters, ...(staticRemotesIter ? [staticRemotesIter] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
212
200
  if (!options.isInitialHost) {
213
201
  done();
214
202
  return;
@@ -66,6 +66,8 @@ async function* moduleFederationSsrDevServer(options, context) {
66
66
  : Array.isArray(options.devRemotes)
67
67
  ? options.devRemotes
68
68
  : [options.devRemotes];
69
+ // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
70
+ process.env.NX_MF_DEV_REMOTES = JSON.stringify(devServeApps);
69
71
  for (const app of knownRemotes) {
70
72
  const [appName] = Array.isArray(app) ? app : [app];
71
73
  const isDev = devServeApps.includes(appName);
@@ -11,6 +11,6 @@
11
11
  </head>
12
12
  <body>
13
13
  <div id="root"></div>
14
- <script type="module" src="/src/main.tsx"></script>
14
+ <script type="module" src="/src/<%= js ? 'main.jsx' : 'main.tsx' %>"></script>
15
15
  </body>
16
16
  </html>
@@ -34,6 +34,7 @@ function createApplicationFiles(host, options) {
34
34
  const templateVariables = {
35
35
  ...(0, devkit_1.names)(options.name),
36
36
  ...options,
37
+ js: !!options.js, // Ensure this is defined in template
37
38
  tmpl: '',
38
39
  offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.appProjectRoot),
39
40
  appTests,
@@ -117,7 +118,9 @@ function createApplicationFiles(host, options) {
117
118
  }
118
119
  (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, styleSolutionSpecificAppFiles), options.appProjectRoot, templateVariables);
119
120
  if (options.js) {
120
- (0, devkit_1.toJS)(host);
121
+ (0, devkit_1.toJS)(host, {
122
+ useJsx: options.bundler === 'vite',
123
+ });
121
124
  }
122
125
  (0, create_ts_config_1.createTsConfig)(host, options.appProjectRoot, 'app', options, relativePathToRootTsConfig);
123
126
  }
@@ -73,6 +73,7 @@ async function hostGeneratorInternal(host, schema) {
73
73
  js: options.js,
74
74
  dynamic: options.dynamic,
75
75
  host: options.name,
76
+ skipPackageJson: options.skipPackageJson,
76
77
  });
77
78
  tasks.push(remoteTask);
78
79
  remotePort++;
@@ -45,7 +45,11 @@ function addModuleFederationFiles(host, options, defaultRemoteManifest) {
45
45
  processWebpackConfig(options, host, 'webpack.config.prod.js');
46
46
  processWebpackConfig(options, host, 'webpack.config.prod.ts');
47
47
  if (!host.exists(pathToMFManifest)) {
48
- host.write(pathToMFManifest, '{}');
48
+ host.write(pathToMFManifest, `{
49
+ ${defaultRemoteManifest
50
+ .map(({ name, port }) => `"${name}": "http://localhost:${port}"`)
51
+ .join(',\n')}
52
+ }`);
49
53
  }
50
54
  }
51
55
  }
@@ -18,6 +18,7 @@ export interface Schema {
18
18
  setParserOptionsProject?: boolean;
19
19
  skipFormat?: boolean;
20
20
  skipNxJson?: boolean;
21
+ skipPackageJson?: boolean;
21
22
  ssr?: boolean;
22
23
  strict?: boolean;
23
24
  style: SupportedStyles;
@@ -177,6 +177,12 @@
177
177
  "type": "boolean",
178
178
  "description": "Whether the module federation configuration and webpack configuration files should use TS. When --js is used, this flag is ignored.",
179
179
  "default": true
180
+ },
181
+ "skipPackageJson": {
182
+ "description": "Do not add dependencies to `package.json`.",
183
+ "type": "boolean",
184
+ "default": false,
185
+ "x-priority": "internal"
180
186
  }
181
187
  },
182
188
  "required": ["name"],
@@ -2,9 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addRemoteToDynamicHost = addRemoteToDynamicHost;
4
4
  function addRemoteToDynamicHost(tree, remoteName, remotePort, pathToMfManifest) {
5
- const current = tree.read(pathToMfManifest, 'utf8');
6
- tree.write(pathToMfManifest, JSON.stringify({
7
- ...JSON.parse(current),
8
- [remoteName]: `http://localhost:${remotePort}`,
9
- }));
5
+ if (tree.exists(pathToMfManifest)) {
6
+ const current = tree.read(pathToMfManifest, 'utf8');
7
+ tree.write(pathToMfManifest, JSON.stringify({
8
+ ...JSON.parse(current),
9
+ [remoteName]: `http://localhost:${remotePort}`,
10
+ }));
11
+ }
10
12
  }
@@ -20,6 +20,7 @@ export interface Schema {
20
20
  setParserOptionsProject?: boolean;
21
21
  skipFormat: boolean;
22
22
  skipNxJson?: boolean;
23
+ skipPackageJson?: boolean;
23
24
  ssr?: boolean;
24
25
  strict?: boolean;
25
26
  style: SupportedStyles;
@@ -176,6 +176,12 @@
176
176
  "type": "boolean",
177
177
  "description": "Whether the module federation configuration and webpack configuration files should use TS. When --js is used, this flag is ignored.",
178
178
  "default": true
179
+ },
180
+ "skipPackageJson": {
181
+ "description": "Do not add dependencies to `package.json`.",
182
+ "type": "boolean",
183
+ "default": false,
184
+ "x-priority": "internal"
179
185
  }
180
186
  },
181
187
  "required": ["name"],
@@ -31,7 +31,19 @@ async function withModuleFederationForSSR(options, configOverride) {
31
31
  * Apply user-defined config overrides
32
32
  */
33
33
  ...(configOverride ? configOverride : {}),
34
+ runtimePlugins: process.env.NX_MF_DEV_REMOTES &&
35
+ !options.disableNxRuntimeLibraryControlPlugin
36
+ ? [
37
+ ...(configOverride?.runtimePlugins ?? []),
38
+ require.resolve('@nx/webpack/src/utils/module-federation/plugins/runtime-library-control.plugin.js'),
39
+ ]
40
+ : configOverride?.runtimePlugins,
34
41
  }, {}), sharedLibraries.getReplacementPlugin());
42
+ // The env var is only set from the module-federation-dev-server
43
+ // Attach the runtime plugin
44
+ config.plugins.push(new (require('webpack').DefinePlugin)({
45
+ 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
46
+ }));
35
47
  return config;
36
48
  };
37
49
  }
@@ -52,7 +52,19 @@ async function withModuleFederation(options, configOverride) {
52
52
  * Apply user-defined config overrides
53
53
  */
54
54
  ...(configOverride ? configOverride : {}),
55
+ runtimePlugins: process.env.NX_MF_DEV_REMOTES &&
56
+ !options.disableNxRuntimeLibraryControlPlugin
57
+ ? [
58
+ ...(configOverride?.runtimePlugins ?? []),
59
+ require.resolve('@nx/webpack/src/utils/module-federation/plugins/runtime-library-control.plugin.js'),
60
+ ]
61
+ : configOverride?.runtimePlugins,
55
62
  }), sharedLibraries.getReplacementPlugin());
63
+ // The env var is only set from the module-federation-dev-server
64
+ // Attach the runtime plugin
65
+ config.plugins.push(new (require('webpack').DefinePlugin)({
66
+ 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
67
+ }));
56
68
  return config;
57
69
  };
58
70
  }
@@ -5,7 +5,7 @@ const devkit_1 = require("@nx/devkit");
5
5
  function addMfEnvToTargetDefaultInputs(tree) {
6
6
  const nxJson = (0, devkit_1.readNxJson)(tree);
7
7
  const webpackExecutor = '@nx/webpack:webpack';
8
- const mfEnvVar = 'NX_MF_DEV_SERVER_STATIC_REMOTES';
8
+ const mfEnvVar = 'NX_MF_DEV_REMOTES';
9
9
  nxJson.targetDefaults ??= {};
10
10
  nxJson.targetDefaults[webpackExecutor] ??= {};
11
11
  nxJson.targetDefaults[webpackExecutor].inputs ??= [
@@ -36,7 +36,7 @@ export declare const typesExpressVersion = "4.17.17";
36
36
  export declare const isbotVersion = "^3.6.5";
37
37
  export declare const corsVersion = "~2.8.5";
38
38
  export declare const typesCorsVersion = "~2.8.12";
39
- export declare const moduleFederationNodeVersion = "^2.3.0";
39
+ export declare const moduleFederationNodeVersion = "~2.4.0";
40
40
  export declare const moduleFederationEnhancedVersion = "~0.2.3";
41
41
  export declare const lessVersion = "3.12.2";
42
42
  export declare const sassVersion = "^1.55.0";
@@ -42,7 +42,7 @@ exports.typesExpressVersion = '4.17.17';
42
42
  exports.isbotVersion = '^3.6.5';
43
43
  exports.corsVersion = '~2.8.5';
44
44
  exports.typesCorsVersion = '~2.8.12';
45
- exports.moduleFederationNodeVersion = '^2.3.0';
45
+ exports.moduleFederationNodeVersion = '~2.4.0';
46
46
  exports.moduleFederationEnhancedVersion = '~0.2.3';
47
47
  // style preprocessors
48
48
  exports.lessVersion = '3.12.2';