@nx/react 20.2.0-canary.20241203-6b87005 → 20.2.0-canary.20241205-15060e3

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 (36) hide show
  1. package/generators.json +4 -2
  2. package/package.json +6 -6
  3. package/plugins/bundle-rollup.js +2 -2
  4. package/src/executors/module-federation-dev-server/lib/index.d.ts +2 -0
  5. package/src/executors/module-federation-dev-server/lib/index.js +5 -0
  6. package/src/executors/module-federation-dev-server/lib/normalize-options.d.ts +4 -0
  7. package/src/executors/module-federation-dev-server/lib/normalize-options.js +19 -0
  8. package/src/executors/module-federation-dev-server/lib/start-remotes.d.ts +5 -0
  9. package/src/executors/module-federation-dev-server/lib/start-remotes.js +33 -0
  10. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.d.ts +1 -1
  11. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.js +6 -108
  12. package/src/executors/module-federation-dev-server/schema.d.ts +9 -7
  13. package/src/executors/module-federation-dev-server/schema.json +14 -10
  14. package/src/executors/module-federation-ssr-dev-server/lib/index.d.ts +2 -0
  15. package/src/executors/module-federation-ssr-dev-server/lib/index.js +5 -0
  16. package/src/executors/module-federation-ssr-dev-server/lib/normalize-options.d.ts +4 -0
  17. package/src/executors/module-federation-ssr-dev-server/lib/normalize-options.js +23 -0
  18. package/src/executors/module-federation-ssr-dev-server/lib/start-remotes.d.ts +5 -0
  19. package/src/executors/module-federation-ssr-dev-server/lib/start-remotes.js +34 -0
  20. package/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.d.ts +1 -17
  21. package/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.js +5 -151
  22. package/src/executors/module-federation-ssr-dev-server/schema.d.ts +29 -0
  23. package/src/executors/module-federation-ssr-dev-server/schema.json +13 -9
  24. package/src/executors/module-federation-static-server/module-federation-static-server.impl.js +7 -7
  25. package/src/executors/module-federation-static-server/schema.json +1 -1
  26. package/src/generators/component-story/component-story.js +1 -2
  27. package/src/generators/federate-module/schema.json +14 -8
  28. package/src/generators/host/schema.json +9 -8
  29. package/src/generators/library/lib/add-rollup-build-target.js +30 -27
  30. package/src/generators/library/library.js +6 -0
  31. package/src/generators/remote/lib/update-host-with-remote.js +2 -2
  32. package/src/generators/remote/schema.json +9 -8
  33. package/src/generators/stories/stories.js +5 -2
  34. package/src/generators/storybook-configuration/configuration.js +2 -2
  35. package/src/utils/build-static.remotes.d.ts +0 -4
  36. package/src/utils/build-static.remotes.js +0 -65
package/generators.json CHANGED
@@ -64,13 +64,15 @@
64
64
  "factory": "./src/generators/host/host",
65
65
  "schema": "./src/generators/host/schema.json",
66
66
  "x-type": "application",
67
- "description": "Generate a host react application"
67
+ "description": "Generate a host react application",
68
+ "aliases": ["consumer"]
68
69
  },
69
70
  "remote": {
70
71
  "factory": "./src/generators/remote/remote",
71
72
  "schema": "./src/generators/remote/schema.json",
72
73
  "x-type": "application",
73
- "description": "Generate a remote react application"
74
+ "description": "Generate a remote react application",
75
+ "aliases": ["producer"]
74
76
  },
75
77
  "cypress-component-configuration": {
76
78
  "factory": "./src/generators/cypress-component-configuration/cypress-component-configuration#cypressComponentConfigGenerator",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/react",
3
- "version": "20.2.0-canary.20241203-6b87005",
3
+ "version": "20.2.0-canary.20241205-15060e3",
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": {
@@ -38,11 +38,11 @@
38
38
  "minimatch": "9.0.3",
39
39
  "picocolors": "^1.1.0",
40
40
  "tslib": "^2.3.0",
41
- "@nx/devkit": "20.2.0-canary.20241203-6b87005",
42
- "@nx/js": "20.2.0-canary.20241203-6b87005",
43
- "@nx/eslint": "20.2.0-canary.20241203-6b87005",
44
- "@nx/web": "20.2.0-canary.20241203-6b87005",
45
- "@nx/module-federation": "20.2.0-canary.20241203-6b87005",
41
+ "@nx/devkit": "20.2.0-canary.20241205-15060e3",
42
+ "@nx/js": "20.2.0-canary.20241205-15060e3",
43
+ "@nx/eslint": "20.2.0-canary.20241205-15060e3",
44
+ "@nx/web": "20.2.0-canary.20241205-15060e3",
45
+ "@nx/module-federation": "20.2.0-canary.20241205-15060e3",
46
46
  "express": "^4.19.2",
47
47
  "http-proxy-middleware": "^3.0.3"
48
48
  },
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- // TODO(v22): Remove this in Nx 22 and migrate to explicit rollup.config.js files.
3
+ // TODO(v22): Remove this in Nx 22 and migrate to explicit rollup.config.cjs files.
4
4
  /**
5
- * @deprecated Use `withNx` function from `@nx/rollup/with-nx` in your rollup.config.js file instead. Use `nx g @nx/rollup:convert-to-inferred` to generate the rollup.config.js file if it does not exist.
5
+ * @deprecated Use `withNx` function from `@nx/rollup/with-nx` in your rollup.config.cjs file instead. Use `nx g @nx/rollup:convert-to-inferred` to generate the rollup.config.cjs file if it does not exist.
6
6
  */
7
7
  function getRollupOptions(options) {
8
8
  const extraGlobals = {
@@ -0,0 +1,2 @@
1
+ export * from './normalize-options';
2
+ export * from './start-remotes';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./normalize-options"), exports);
5
+ tslib_1.__exportStar(require("./start-remotes"), exports);
@@ -0,0 +1,4 @@
1
+ import { ExecutorContext } from '@nx/devkit';
2
+ import { ModuleFederationDevServerOptions, NormalizedModuleFederationDevServerOptions } from '../schema';
3
+ export declare function getBuildOptions(buildTarget: string, context: ExecutorContext): any;
4
+ export declare function normalizeOptions(options: ModuleFederationDevServerOptions): NormalizedModuleFederationDevServerOptions;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBuildOptions = getBuildOptions;
4
+ exports.normalizeOptions = normalizeOptions;
5
+ const devkit_1 = require("@nx/devkit");
6
+ function getBuildOptions(buildTarget, context) {
7
+ const target = (0, devkit_1.parseTargetString)(buildTarget, context);
8
+ const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
9
+ return {
10
+ ...buildOptions,
11
+ };
12
+ }
13
+ function normalizeOptions(options) {
14
+ return {
15
+ ...options,
16
+ devRemotes: options.devRemotes ?? [],
17
+ verbose: options.verbose ?? false,
18
+ };
19
+ }
@@ -0,0 +1,5 @@
1
+ import { ExecutorContext, ProjectConfiguration } from '@nx/devkit';
2
+ import { NormalizedModuleFederationDevServerOptions } from '../schema';
3
+ export declare function startRemotes(remotes: string[], workspaceProjects: Record<string, ProjectConfiguration>, options: Pick<NormalizedModuleFederationDevServerOptions, 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose'>, context: ExecutorContext, target?: 'serve' | 'serve-static'): Promise<AsyncIterable<{
4
+ success: boolean;
5
+ }>[]>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startRemotes = startRemotes;
4
+ const devkit_1 = require("@nx/devkit");
5
+ async function startRemotes(remotes, workspaceProjects, options, context, target = 'serve') {
6
+ const remoteIters = [];
7
+ for (const app of remotes) {
8
+ const remoteProjectServeTarget = workspaceProjects[app].targets[target];
9
+ const isUsingModuleFederationDevServerExecutor = remoteProjectServeTarget.executor.includes('module-federation-dev-server');
10
+ const configurationOverride = options.devRemotes?.find((r) => typeof r !== 'string' && r.remoteName === app)?.configuration;
11
+ const defaultOverrides = {
12
+ ...(options.host ? { host: options.host } : {}),
13
+ ...(options.ssl ? { ssl: options.ssl } : {}),
14
+ ...(options.sslCert ? { sslCert: options.sslCert } : {}),
15
+ ...(options.sslKey ? { sslKey: options.sslKey } : {}),
16
+ };
17
+ const overrides = target === 'serve'
18
+ ? {
19
+ watch: true,
20
+ ...(isUsingModuleFederationDevServerExecutor
21
+ ? { isInitialHost: false }
22
+ : {}),
23
+ ...defaultOverrides,
24
+ }
25
+ : { ...defaultOverrides };
26
+ remoteIters.push(await (0, devkit_1.runExecutor)({
27
+ project: app,
28
+ target,
29
+ configuration: configurationOverride ?? context.configurationName,
30
+ }, overrides, context));
31
+ }
32
+ return remoteIters;
33
+ }
@@ -1,6 +1,6 @@
1
1
  import { ExecutorContext } from '@nx/devkit';
2
2
  import { ModuleFederationDevServerOptions } from './schema';
3
- export default function moduleFederationDevServer(options: ModuleFederationDevServerOptions, context: ExecutorContext): AsyncIterableIterator<{
3
+ export default function moduleFederationDevServer(schema: ModuleFederationDevServerOptions, context: ExecutorContext): AsyncIterableIterator<{
4
4
  success: boolean;
5
5
  baseUrl?: string;
6
6
  }>;
@@ -4,94 +4,14 @@ exports.default = moduleFederationDevServer;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const dev_server_impl_1 = require("@nx/webpack/src/executors/dev-server/dev-server.impl");
6
6
  const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-server.impl");
7
- const utils_1 = require("@nx/module-federation/src/utils");
7
+ const utils_1 = require("@nx/module-federation/src/executors/utils");
8
8
  const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
9
9
  const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
10
10
  const fs_1 = require("fs");
11
11
  const path_1 = require("path");
12
- const build_static_remotes_1 = require("../../utils/build-static.remotes");
13
- function getBuildOptions(buildTarget, context) {
14
- const target = (0, devkit_1.parseTargetString)(buildTarget, context);
15
- const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
16
- return {
17
- ...buildOptions,
18
- };
19
- }
20
- function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
21
- if (!staticRemotesConfig.remotes ||
22
- staticRemotesConfig.remotes.length === 0) {
23
- return;
24
- }
25
- let shouldMoveToCommonLocation = false;
26
- let commonOutputDirectory;
27
- for (const app of staticRemotesConfig.remotes) {
28
- const remoteBasePath = staticRemotesConfig.config[app].basePath;
29
- if (!commonOutputDirectory) {
30
- commonOutputDirectory = remoteBasePath;
31
- }
32
- else if (commonOutputDirectory !== remoteBasePath) {
33
- shouldMoveToCommonLocation = true;
34
- break;
35
- }
36
- }
37
- if (shouldMoveToCommonLocation) {
38
- commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
39
- for (const app of staticRemotesConfig.remotes) {
40
- const remoteConfig = staticRemotesConfig.config[app];
41
- (0, fs_1.cpSync)(remoteConfig.outputPath, (0, path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
42
- force: true,
43
- recursive: true,
44
- });
45
- }
46
- }
47
- const staticRemotesIter = (0, file_server_impl_1.default)({
48
- cors: true,
49
- watch: false,
50
- staticFilePath: commonOutputDirectory,
51
- parallel: false,
52
- spa: false,
53
- withDeps: false,
54
- host: options.host,
55
- port: options.staticRemotesPort,
56
- ssl: options.ssl,
57
- sslCert: options.sslCert,
58
- sslKey: options.sslKey,
59
- cacheSeconds: -1,
60
- }, context);
61
- return staticRemotesIter;
62
- }
63
- async function startRemotes(remotes, context, options, target = 'serve') {
64
- const remoteIters = [];
65
- for (const app of remotes) {
66
- const remoteProjectServeTarget = context.projectGraph.nodes[app].data.targets[target];
67
- const isUsingModuleFederationDevServerExecutor = remoteProjectServeTarget.executor.includes('module-federation-dev-server');
68
- const configurationOverride = options.devRemotes?.find((r) => typeof r !== 'string' && r.remoteName === app)?.configuration;
69
- const defaultOverrides = {
70
- ...(options.host ? { host: options.host } : {}),
71
- ...(options.ssl ? { ssl: options.ssl } : {}),
72
- ...(options.sslCert ? { sslCert: options.sslCert } : {}),
73
- ...(options.sslKey ? { sslKey: options.sslKey } : {}),
74
- };
75
- const overrides = target === 'serve'
76
- ? {
77
- watch: true,
78
- ...(isUsingModuleFederationDevServerExecutor
79
- ? { isInitialHost: false }
80
- : {}),
81
- ...defaultOverrides,
82
- }
83
- : { ...defaultOverrides };
84
- remoteIters.push(await (0, devkit_1.runExecutor)({
85
- project: app,
86
- target,
87
- configuration: configurationOverride ?? context.configurationName,
88
- }, overrides, context));
89
- }
90
- return remoteIters;
91
- }
92
- async function* moduleFederationDevServer(options, context) {
93
- // Force Node to resolve to look for the nx binary that is inside node_modules
94
- const nxBin = require.resolve('nx/bin/nx');
12
+ const lib_1 = require("./lib");
13
+ async function* moduleFederationDevServer(schema, context) {
14
+ const options = (0, lib_1.normalizeOptions)(schema);
95
15
  const currIter = options.static
96
16
  ? (0, file_server_impl_1.default)({
97
17
  ...options,
@@ -103,7 +23,7 @@ async function* moduleFederationDevServer(options, context) {
103
23
  }, context)
104
24
  : (0, dev_server_impl_1.default)(options, context);
105
25
  const p = context.projectsConfigurations.projects[context.projectName];
106
- const buildOptions = getBuildOptions(options.buildTarget, context);
26
+ const buildOptions = (0, lib_1.getBuildOptions)(options.buildTarget, context);
107
27
  let pathToManifestFile = (0, path_1.join)(context.root, p.sourceRoot, 'assets/module-federation.manifest.json');
108
28
  if (options.pathToManifestFile) {
109
29
  const userPathToManifestFile = (0, path_1.join)(context.root, options.pathToManifestFile);
@@ -118,29 +38,7 @@ async function* moduleFederationDevServer(options, context) {
118
38
  if (!options.isInitialHost) {
119
39
  return yield* currIter;
120
40
  }
121
- const moduleFederationConfig = (0, utils_1.getModuleFederationConfig)(buildOptions.tsConfig, context.root, p.root, 'react');
122
- const remoteNames = options.devRemotes?.map((r) => typeof r === 'string' ? r : r.remoteName);
123
- const remotes = (0, utils_1.getRemotes)(remoteNames, options.skipRemotes, moduleFederationConfig, {
124
- projectName: context.projectName,
125
- projectGraph: context.projectGraph,
126
- root: context.root,
127
- }, pathToManifestFile);
128
- options.staticRemotesPort ??= remotes.staticRemotePort;
129
- // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
130
- process.env.NX_MF_DEV_REMOTES = JSON.stringify([
131
- ...(remotes.devRemotes.map((r) => typeof r === 'string' ? r : r.remoteName) ?? []).map((r) => r.replace(/-/g, '_')),
132
- p.name.replace(/-/g, '_'),
133
- ]);
134
- const staticRemotesConfig = (0, utils_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
135
- const mappedLocationsOfStaticRemotes = await (0, build_static_remotes_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options);
136
- const devRemoteIters = await startRemotes(remotes.devRemotes, context, options, 'serve');
137
- const staticRemotesIter = startStaticRemotesFileServer(staticRemotesConfig, context, options);
138
- (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes, options.ssl
139
- ? {
140
- pathToCert: (0, path_1.join)(devkit_1.workspaceRoot, options.sslCert),
141
- pathToKey: (0, path_1.join)(devkit_1.workspaceRoot, options.sslKey),
142
- }
143
- : undefined);
41
+ const { staticRemotesIter, devRemoteIters, remotes } = await (0, utils_1.startRemoteIterators)(options, context, lib_1.startRemotes, pathToManifestFile, 'react');
144
42
  return yield* (0, async_iterable_1.combineAsyncIterables)(currIter, ...devRemoteIters, ...(staticRemotesIter ? [staticRemotesIter] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
145
43
  if (!options.isInitialHost) {
146
44
  done();
@@ -1,17 +1,19 @@
1
1
  import { WebDevServerOptions } from '@nx/webpack';
2
+ import { DevRemoteDefinition } from '@nx/module-federation/src/executors/utils';
2
3
 
3
4
  export type ModuleFederationDevServerOptions = WebDevServerOptions & {
4
- devRemotes?: (
5
- | string
6
- | {
7
- remoteName: string;
8
- configuration: string;
9
- }
10
- )[];
5
+ devRemotes?: DevRemoteDefinition[];
11
6
  skipRemotes?: string[];
12
7
  static?: boolean;
13
8
  isInitialHost?: boolean;
14
9
  parallel?: number;
15
10
  staticRemotesPort?: number;
16
11
  pathToManifestFile?: string;
12
+ verbose?: boolean;
17
13
  };
14
+
15
+ export type NormalizedModuleFederationDevServerOptions =
16
+ ModuleFederationDevServerOptions & {
17
+ devRemotes: DevRemoteDefinition[];
18
+ verbose: boolean;
19
+ };
@@ -28,16 +28,18 @@
28
28
  }
29
29
  ]
30
30
  },
31
- "description": "List of remote applications to run in development mode (i.e. using serve target).",
32
- "x-priority": "important"
31
+ "description": "List of Producer (remote) applications to run in development mode (i.e. using serve target).",
32
+ "x-priority": "important",
33
+ "alias": "devProducers"
33
34
  },
34
35
  "skipRemotes": {
35
36
  "type": "array",
36
37
  "items": {
37
38
  "type": "string"
38
39
  },
39
- "description": "List of remote applications to not automatically serve, either statically or in development mode. This will not remove the remotes from the `module-federation.config` file, and therefore the application may still try to fetch these remotes.\nThis option is useful if you have other means for serving the `remote` application(s).\n**NOTE:** Remotes that are not in the workspace will be skipped automatically.",
40
- "x-priority": "important"
40
+ "description": "List of Producer (remote) applications to not automatically serve, either statically or in development mode. This will not remove the Producers (remotes) from the `module-federation.config` file, and therefore the application may still try to fetch these Producers (remotes).\nThis option is useful if you have other means for serving the Producer (remote) application(s).\n**NOTE:** Producers (remotes) that are not in the workspace will be skipped automatically.",
41
+ "x-priority": "important",
42
+ "alias": "skipProducers"
41
43
  },
42
44
  "buildTarget": {
43
45
  "type": "string",
@@ -111,25 +113,27 @@
111
113
  },
112
114
  "static": {
113
115
  "type": "boolean",
114
- "description": "Whether to use a static file server instead of the webpack-dev-server. This should be used for remote applications that are also host applications."
116
+ "description": "Whether to use a static file server instead of the webpack-dev-server. This should be used for Producer (remote) applications that are also Consumer (host) applications."
115
117
  },
116
118
  "isInitialHost": {
117
119
  "type": "boolean",
118
- "description": "Whether the host that is running this executor is the first in the project tree to do so.",
120
+ "description": "Whether the Consumer (host) that is running this executor is the first in the project tree to do so.",
119
121
  "default": true,
120
- "x-priority": "internal"
122
+ "x-priority": "internal",
123
+ "alias": "isInitialConsumer"
121
124
  },
122
125
  "parallel": {
123
126
  "type": "number",
124
- "description": "Max number of parallel processes for building static remotes"
127
+ "description": "Max number of parallel processes for building static Producers (remotes)"
125
128
  },
126
129
  "staticRemotesPort": {
127
130
  "type": "number",
128
- "description": "The port at which to serve the file-server for the static remotes."
131
+ "description": "The port at which to serve the file-server for the static Producers (remotes).",
132
+ "alias": "staticProducersPort"
129
133
  },
130
134
  "pathToManifestFile": {
131
135
  "type": "string",
132
- "description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
136
+ "description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic Producer (remote) applications relative to the workspace root."
133
137
  }
134
138
  },
135
139
  "examplesFile": "../../../docs/module-federation-dev-server-examples.md"
@@ -0,0 +1,2 @@
1
+ export * from './normalize-options';
2
+ export * from './start-remotes';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./normalize-options"), exports);
5
+ tslib_1.__exportStar(require("./start-remotes"), exports);
@@ -0,0 +1,4 @@
1
+ import { ModuleFederationSsrDevServerOptions, NormalizedModuleFederationSsrDevServerOptions } from '../schema';
2
+ import { ExecutorContext } from '@nx/devkit';
3
+ export declare function normalizeOptions(options: ModuleFederationSsrDevServerOptions): NormalizedModuleFederationSsrDevServerOptions;
4
+ export declare function getBuildOptions(buildTarget: string, context: ExecutorContext): any;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeOptions = normalizeOptions;
4
+ exports.getBuildOptions = getBuildOptions;
5
+ const path_1 = require("path");
6
+ const devkit_1 = require("@nx/devkit");
7
+ function normalizeOptions(options) {
8
+ return {
9
+ ...options,
10
+ devRemotes: options.devRemotes ?? [],
11
+ verbose: options.verbose ?? false,
12
+ ssl: options.ssl ?? false,
13
+ sslCert: options.sslCert ? (0, path_1.join)(devkit_1.workspaceRoot, options.sslCert) : undefined,
14
+ sslKey: options.sslKey ? (0, path_1.join)(devkit_1.workspaceRoot, options.sslKey) : undefined,
15
+ };
16
+ }
17
+ function getBuildOptions(buildTarget, context) {
18
+ const target = (0, devkit_1.parseTargetString)(buildTarget, context);
19
+ const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
20
+ return {
21
+ ...buildOptions,
22
+ };
23
+ }
@@ -0,0 +1,5 @@
1
+ import { ModuleFederationSsrDevServerOptions } from '../schema';
2
+ import { ExecutorContext, ProjectConfiguration } from '@nx/devkit';
3
+ export declare function startRemotes(remotes: string[], workspaceProjects: Record<string, ProjectConfiguration>, options: Partial<Pick<ModuleFederationSsrDevServerOptions, 'devRemotes' | 'host' | 'ssl' | 'sslCert' | 'sslKey' | 'verbose'>>, context: ExecutorContext): Promise<AsyncIterable<{
4
+ success: boolean;
5
+ }>[]>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startRemotes = startRemotes;
4
+ const devkit_1 = require("@nx/devkit");
5
+ async function startRemotes(remotes, workspaceProjects, options, context) {
6
+ const remoteIters = [];
7
+ const target = 'serve';
8
+ for (const app of remotes) {
9
+ const remoteProjectServeTarget = workspaceProjects[app].targets[target];
10
+ const isUsingModuleFederationSsrDevServerExecutor = remoteProjectServeTarget.executor.includes('module-federation-ssr-dev-server');
11
+ const configurationOverride = options.devRemotes?.find((remote) => typeof remote !== 'string' && remote.remoteName === app)?.configuration;
12
+ {
13
+ const defaultOverrides = {
14
+ ...(options.host ? { host: options.host } : {}),
15
+ ...(options.ssl ? { ssl: options.ssl } : {}),
16
+ ...(options.sslCert ? { sslCert: options.sslCert } : {}),
17
+ ...(options.sslKey ? { sslKey: options.sslKey } : {}),
18
+ };
19
+ const overrides = {
20
+ watch: true,
21
+ ...defaultOverrides,
22
+ ...(isUsingModuleFederationSsrDevServerExecutor
23
+ ? { isInitialHost: false }
24
+ : {}),
25
+ };
26
+ remoteIters.push(await (0, devkit_1.runExecutor)({
27
+ project: app,
28
+ target,
29
+ configuration: configurationOverride ?? context.configurationName,
30
+ }, overrides, context));
31
+ }
32
+ }
33
+ return remoteIters;
34
+ }
@@ -1,19 +1,3 @@
1
1
  import { ExecutorContext } from '@nx/devkit';
2
- import { WebSsrDevServerOptions } from '@nx/webpack/src/executors/ssr-dev-server/schema';
3
- type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & {
4
- devRemotes?: (string | {
5
- remoteName: string;
6
- configuration: string;
7
- })[];
8
- skipRemotes?: string[];
9
- host: string;
10
- pathToManifestFile?: string;
11
- staticRemotesPort?: number;
12
- parallel?: number;
13
- ssl?: boolean;
14
- sslKey?: string;
15
- sslCert?: string;
16
- isInitialHost?: boolean;
17
- };
2
+ import { ModuleFederationSsrDevServerOptions } from './schema';
18
3
  export default function moduleFederationSsrDevServer(ssrDevServerOptions: ModuleFederationSsrDevServerOptions, context: ExecutorContext): AsyncGenerator<any, any, any>;
19
- export {};
@@ -4,141 +4,16 @@ exports.default = moduleFederationSsrDevServer;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const ssr_dev_server_impl_1 = require("@nx/webpack/src/executors/ssr-dev-server/ssr-dev-server.impl");
6
6
  const path_1 = require("path");
7
- const utils_1 = require("@nx/module-federation/src/utils");
7
+ const utils_1 = require("@nx/module-federation/src/executors/utils");
8
8
  const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
9
- const child_process_1 = require("child_process");
10
9
  const fs_1 = require("fs");
11
- const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-server.impl");
12
- const cache_directory_1 = require("nx/src/utils/cache-directory");
13
10
  const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
14
- function normalizeOptions(options) {
15
- return {
16
- ...options,
17
- ssl: options.ssl ?? false,
18
- sslCert: options.sslCert ? (0, path_1.join)(devkit_1.workspaceRoot, options.sslCert) : undefined,
19
- sslKey: options.sslKey ? (0, path_1.join)(devkit_1.workspaceRoot, options.sslKey) : undefined,
20
- };
21
- }
22
- function getBuildOptions(buildTarget, context) {
23
- const target = (0, devkit_1.parseTargetString)(buildTarget, context);
24
- const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
25
- return {
26
- ...buildOptions,
27
- };
28
- }
29
- async function* startSsrStaticRemotesFileServer(ssrStaticRemotesConfig, context, options) {
30
- if (ssrStaticRemotesConfig.remotes.length === 0) {
31
- yield { success: true };
32
- return;
33
- }
34
- // The directories are usually generated with /browser and /server suffixes so we need to copy them to a common directory
35
- const commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
36
- for (const app of ssrStaticRemotesConfig.remotes) {
37
- const remoteConfig = ssrStaticRemotesConfig.config[app];
38
- (0, fs_1.cpSync)(remoteConfig.outputPath, (0, path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
39
- force: true,
40
- recursive: true,
41
- });
42
- }
43
- const staticRemotesIter = (0, file_server_impl_1.default)({
44
- cors: true,
45
- watch: false,
46
- staticFilePath: commonOutputDirectory,
47
- parallel: false,
48
- spa: false,
49
- withDeps: false,
50
- host: options.host,
51
- port: options.staticRemotesPort,
52
- ssl: options.ssl,
53
- sslCert: options.sslCert,
54
- sslKey: options.sslKey,
55
- cacheSeconds: -1,
56
- }, context);
57
- yield* staticRemotesIter;
58
- }
59
- async function startRemotes(remotes, context, options) {
60
- const remoteIters = [];
61
- const target = 'serve';
62
- for (const app of remotes) {
63
- const remoteProjectServeTarget = context.projectGraph.nodes[app].data.targets[target];
64
- const isUsingModuleFederationSsrDevServerExecutor = remoteProjectServeTarget.executor.includes('module-federation-ssr-dev-server');
65
- const configurationOverride = options.devRemotes?.find((remote) => typeof remote !== 'string' && remote.remoteName === app)?.configuration;
66
- {
67
- const defaultOverrides = {
68
- ...(options.host ? { host: options.host } : {}),
69
- ...(options.ssl ? { ssl: options.ssl } : {}),
70
- ...(options.sslCert ? { sslCert: options.sslCert } : {}),
71
- ...(options.sslKey ? { sslKey: options.sslKey } : {}),
72
- };
73
- const overrides = {
74
- watch: true,
75
- ...defaultOverrides,
76
- ...(isUsingModuleFederationSsrDevServerExecutor
77
- ? { isInitialHost: false }
78
- : {}),
79
- };
80
- remoteIters.push(await (0, devkit_1.runExecutor)({
81
- project: app,
82
- target,
83
- configuration: configurationOverride ?? context.configurationName,
84
- }, overrides, context));
85
- }
86
- }
87
- return remoteIters;
88
- }
89
- async function buildSsrStaticRemotes(staticRemotesConfig, nxBin, context, options) {
90
- if (!staticRemotesConfig.remotes.length) {
91
- return;
92
- }
93
- devkit_1.logger.info(`Nx is building ${staticRemotesConfig.remotes.length} static remotes...`);
94
- const mapLocationOfRemotes = {};
95
- for (const remoteApp of staticRemotesConfig.remotes) {
96
- mapLocationOfRemotes[remoteApp] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig.config[remoteApp].urlSegment}`;
97
- }
98
- await new Promise((resolve) => {
99
- const childProcess = (0, child_process_1.fork)(nxBin, [
100
- 'run-many',
101
- '--target=server',
102
- '--projects',
103
- staticRemotesConfig.remotes.join(','),
104
- ...(context.configurationName
105
- ? [`--configuration=${context.configurationName}`]
106
- : []),
107
- ...(options.parallel ? [`--parallel=${options.parallel}`] : []),
108
- ], {
109
- cwd: context.root,
110
- stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
111
- });
112
- // Add a listener to the child process to capture the build log
113
- const remoteBuildLogFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`);
114
- const remoteBuildLogStream = (0, fs_1.createWriteStream)(remoteBuildLogFile);
115
- childProcess.stdout.on('data', (data) => {
116
- const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
117
- const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
118
- remoteBuildLogStream.write(stdoutString);
119
- // in addition to writing into the stdout stream, also show error directly in console
120
- // so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
121
- if (stdoutString.includes('ERROR in')) {
122
- devkit_1.logger.log(stdoutString);
123
- }
124
- if (stdoutString.includes('Successfully ran target server')) {
125
- childProcess.stdout.removeAllListeners('data');
126
- devkit_1.logger.info(`Nx Built ${staticRemotesConfig.remotes.length} static remotes.`);
127
- resolve();
128
- }
129
- });
130
- process.on('SIGTERM', () => childProcess.kill('SIGTERM'));
131
- process.on('exit', () => childProcess.kill('SIGTERM'));
132
- });
133
- return mapLocationOfRemotes;
134
- }
11
+ const lib_1 = require("./lib");
135
12
  async function* moduleFederationSsrDevServer(ssrDevServerOptions, context) {
136
- const options = normalizeOptions(ssrDevServerOptions);
137
- // Force Node to resolve to look for the nx binary that is inside node_modules
138
- const nxBin = require.resolve('nx/bin/nx');
13
+ const options = (0, lib_1.normalizeOptions)(ssrDevServerOptions);
139
14
  let iter = (0, ssr_dev_server_impl_1.default)(options, context);
140
15
  const projectConfig = context.projectsConfigurations.projects[context.projectName];
141
- const buildOptions = getBuildOptions(options.browserTarget, context);
16
+ const buildOptions = (0, lib_1.getBuildOptions)(options.browserTarget, context);
142
17
  let pathToManifestFile = (0, path_1.join)(context.root, projectConfig.sourceRoot, 'assets/module-federation.manifest.json');
143
18
  if (options.pathToManifestFile) {
144
19
  const userPathToManifestFile = (0, path_1.join)(context.root, options.pathToManifestFile);
@@ -153,28 +28,7 @@ async function* moduleFederationSsrDevServer(ssrDevServerOptions, context) {
153
28
  if (!options.isInitialHost) {
154
29
  return yield* iter;
155
30
  }
156
- const moduleFederationConfig = (0, utils_1.getModuleFederationConfig)(buildOptions.tsConfig, context.root, projectConfig.root, 'react');
157
- const remoteNames = options.devRemotes?.map((remote) => typeof remote === 'string' ? remote : remote.remoteName);
158
- const remotes = (0, utils_1.getRemotes)(remoteNames, options.skipRemotes, moduleFederationConfig, {
159
- projectName: context.projectName,
160
- projectGraph: context.projectGraph,
161
- root: context.root,
162
- }, pathToManifestFile);
163
- options.staticRemotesPort ??= remotes.staticRemotePort;
164
- process.env.NX_MF_DEV_REMOTES = JSON.stringify([
165
- ...(remotes.devRemotes.map((r) => typeof r === 'string' ? r : r.remoteName) ?? []).map((r) => r.replace(/-/g, '_')),
166
- projectConfig.name.replace(/-/g, '_'),
167
- ]);
168
- const staticRemotesConfig = (0, utils_1.parseStaticSsrRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
169
- const mappedLocationsOfStaticRemotes = await buildSsrStaticRemotes(staticRemotesConfig, nxBin, context, options);
170
- const devRemoteIters = await startRemotes(remotes.devRemotes, context, options);
171
- const staticRemotesIter = startSsrStaticRemotesFileServer(staticRemotesConfig, context, options);
172
- (0, utils_1.startSsrRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes, options.ssl
173
- ? {
174
- pathToCert: options.sslCert,
175
- pathToKey: options.sslKey,
176
- }
177
- : undefined);
31
+ const { staticRemotesIter, devRemoteIters, remotes } = await (0, utils_1.startRemoteIterators)(options, context, lib_1.startRemotes, pathToManifestFile, 'react', true);
178
32
  const combined = (0, async_iterable_1.combineAsyncIterables)(staticRemotesIter, ...devRemoteIters);
179
33
  let refs = 1 + (devRemoteIters?.length ?? 0);
180
34
  for await (const result of combined) {
@@ -0,0 +1,29 @@
1
+ import { WebSsrDevServerOptions } from '@nx/webpack/src/executors/ssr-dev-server/schema';
2
+ import { DevRemoteDefinition } from '@nx/module-federation/src/executors/utils';
3
+
4
+ export type ModuleFederationSsrDevServerOptions = WebSsrDevServerOptions & {
5
+ devRemotes?: (
6
+ | string
7
+ | {
8
+ remoteName: string;
9
+ configuration: string;
10
+ }
11
+ )[];
12
+
13
+ skipRemotes?: string[];
14
+ host: string;
15
+ pathToManifestFile?: string;
16
+ staticRemotesPort?: number;
17
+ parallel?: number;
18
+ ssl?: boolean;
19
+ sslKey?: string;
20
+ sslCert?: string;
21
+ isInitialHost?: boolean;
22
+ verbose?: boolean;
23
+ };
24
+
25
+ export type NormalizedModuleFederationSsrDevServerOptions =
26
+ ModuleFederationSsrDevServerOptions & {
27
+ devRemotes: DevRemoteDefinition[];
28
+ verbose: boolean;
29
+ };
@@ -2,7 +2,7 @@
2
2
  "version": 2,
3
3
  "outputCapture": "direct-nodejs",
4
4
  "title": "Module Federation SSR Dev Server",
5
- "description": "Serve a SSR host application along with its known remotes.",
5
+ "description": "Serve a SSR Consumer (host) application along with its known Producers (remotes).",
6
6
  "cli": "nx",
7
7
  "type": "object",
8
8
  "properties": {
@@ -27,16 +27,18 @@
27
27
  "items": {
28
28
  "type": "string"
29
29
  },
30
- "description": "List of remote applications to run in development mode (i.e. using serve target).",
31
- "x-priority": "important"
30
+ "description": "List of Producer (remote) applications to run in development mode (i.e. using serve target).",
31
+ "x-priority": "important",
32
+ "alias": "devProducers"
32
33
  },
33
34
  "skipRemotes": {
34
35
  "type": "array",
35
36
  "items": {
36
37
  "type": "string"
37
38
  },
38
- "description": "List of remote applications to not automatically serve, either statically or in development mode.",
39
- "x-priority": "important"
39
+ "description": "List of Producer (remote) applications to not automatically serve, either statically or in development mode.",
40
+ "x-priority": "important",
41
+ "alias": "skipProducers"
40
42
  },
41
43
  "host": {
42
44
  "type": "string",
@@ -45,11 +47,12 @@
45
47
  },
46
48
  "staticRemotesPort": {
47
49
  "type": "number",
48
- "description": "The port at which to serve the file-server for the static remotes."
50
+ "description": "The port at which to serve the file-server for the static Producers (remotes).",
51
+ "alias": "staticProducersPort"
49
52
  },
50
53
  "pathToManifestFile": {
51
54
  "type": "string",
52
- "description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
55
+ "description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic Producer (remote) applications relative to the workspace root."
53
56
  },
54
57
  "ssl": {
55
58
  "type": "boolean",
@@ -66,9 +69,10 @@
66
69
  },
67
70
  "isInitialHost": {
68
71
  "type": "boolean",
69
- "description": "Whether the host that is running this executor is the first in the project tree to do so.",
72
+ "description": "Whether the Consumer (host) that is running this executor is the first in the project tree to do so.",
70
73
  "default": true,
71
- "x-priority": "internal"
74
+ "x-priority": "internal",
75
+ "alias": "isInitialConsumer"
72
76
  }
73
77
  },
74
78
  "required": ["browserTarget", "serverTarget"]
@@ -6,7 +6,7 @@ const path_1 = require("path");
6
6
  const devkit_1 = require("@nx/devkit");
7
7
  const fs_1 = require("fs");
8
8
  const utils_1 = require("@nx/module-federation/src/utils");
9
- const build_static_remotes_1 = require("../../utils/build-static.remotes");
9
+ const utils_2 = require("@nx/module-federation/src/executors/utils");
10
10
  const child_process_1 = require("child_process");
11
11
  const process = require("node:process");
12
12
  const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-server.impl");
@@ -58,7 +58,7 @@ async function buildHost(nxBin, buildTarget, context) {
58
58
  }
59
59
  if (stdoutString.includes('Successfully ran target build')) {
60
60
  staticProcess.stdout.removeAllListeners('data');
61
- devkit_1.logger.info(`NX Built host`);
61
+ devkit_1.logger.info(`NX Built Consumer (host)`);
62
62
  res();
63
63
  }
64
64
  });
@@ -67,7 +67,7 @@ async function buildHost(nxBin, buildTarget, context) {
67
67
  staticProcess.stdout.removeAllListeners('data');
68
68
  staticProcess.stderr.removeAllListeners('data');
69
69
  if (code !== 0) {
70
- rej(`Host failed to build. See above for details.`);
70
+ rej(`Consumer (host) failed to build. See above for details.`);
71
71
  }
72
72
  else {
73
73
  res();
@@ -132,8 +132,8 @@ function startProxies(staticRemotesConfig, hostServeOptions, mappedLocationOfHos
132
132
  process.on('SIGTERM', () => proxyServer.close());
133
133
  process.on('exit', () => proxyServer.close());
134
134
  }
135
- devkit_1.logger.info(`NX Static remotes proxies started successfully`);
136
- devkit_1.logger.info(`NX Starting static host proxy...`);
135
+ devkit_1.logger.info(`NX Static Producers (remotes) proxies started successfully`);
136
+ devkit_1.logger.info(`NX Starting static Consumer (host) proxy...`);
137
137
  const expressProxy = express();
138
138
  expressProxy.use(createProxyMiddleware({
139
139
  target: mappedLocationOfHost,
@@ -155,7 +155,7 @@ function startProxies(staticRemotesConfig, hostServeOptions, mappedLocationOfHos
155
155
  .listen(hostServeOptions.port);
156
156
  process.on('SIGTERM', () => proxyServer.close());
157
157
  process.on('exit', () => proxyServer.close());
158
- devkit_1.logger.info('NX Static host proxy started successfully');
158
+ devkit_1.logger.info('NX Static Consumer (host) proxy started successfully');
159
159
  }
160
160
  async function* moduleFederationStaticServer(schema, context) {
161
161
  // Force Node to resolve to look for the nx binary that is inside node_modules
@@ -171,7 +171,7 @@ async function* moduleFederationStaticServer(schema, context) {
171
171
  }, options.pathToManifestFile);
172
172
  const staticRemotesConfig = (0, utils_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
173
173
  options.serveOptions.staticRemotesPort ??= remotes.staticRemotePort;
174
- const mappedLocationsOfStaticRemotes = await (0, build_static_remotes_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options.serveOptions);
174
+ const mappedLocationsOfStaticRemotes = await (0, utils_2.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options.serveOptions);
175
175
  // Build the host
176
176
  const hostUrlSegment = (0, path_1.basename)(options.buildOptions.outputPath);
177
177
  const mappedLocationOfHost = `http${options.serveOptions.ssl ? 's' : ''}://${options.serveOptions.host}:${options.serveOptions.staticRemotesPort}/${hostUrlSegment}`;
@@ -2,7 +2,7 @@
2
2
  "version": 2,
3
3
  "outputCapture": "direct-nodejs",
4
4
  "title": "Module Federation Static Dev Server",
5
- "description": "Serve a host application statically along with it's remotes.",
5
+ "description": "Serve a Consumer (host) application statically along with its Producers (remotes).",
6
6
  "cli": "nx",
7
7
  "type": "object",
8
8
  "properties": {
@@ -13,8 +13,7 @@ function createComponentStoriesFile(host, { project, componentPath, interactionT
13
13
  tsModule = (0, ensure_typescript_1.ensureTypescript)();
14
14
  }
15
15
  const proj = (0, devkit_1.getProjects)(host).get(project);
16
- const sourceRoot = proj.sourceRoot;
17
- const componentFilePath = (0, devkit_1.joinPathFragments)(sourceRoot, componentPath);
16
+ const componentFilePath = (0, devkit_1.joinPathFragments)(proj.sourceRoot ?? proj.root, componentPath);
18
17
  const componentDirectory = componentFilePath.replace(componentFilePath.slice(componentFilePath.lastIndexOf('/')), '');
19
18
  const isPlainJs = componentFilePath.endsWith('.jsx') || componentFilePath.endsWith('.js');
20
19
  const componentFileName = componentFilePath
@@ -3,11 +3,15 @@
3
3
  "cli": "nx",
4
4
  "$id": "NxReactFederateModule",
5
5
  "title": "Federate Module",
6
- "description": "Create a federated module, which can be loaded by a remote host.",
6
+ "description": "Create a federated module, which can be loaded by a Consumer (host) via a Producer (remote).",
7
7
  "examples": [
8
8
  {
9
- "command": "nx g federate-module MyModule --path=./src/component/my-cmp.ts --remote=my-remote-app --remoteDirectory=apps/my-remote-app",
10
- "description": "Create a federated module from my-remote-app, that exposes my-cmp from ./src/component/my-cmp.ts as MyModule."
9
+ "command": "nx g federate-module MyModule --path=./src/component/my-cmp.ts --remote=myRemote --remoteDirectory=apps/myRemote",
10
+ "description": "Create a federated module from myRemote, that exposes my-cmp from ./src/component/my-cmp.ts as MyModule."
11
+ },
12
+ {
13
+ "command": "nx g federate-module MyModule --path=./src/component/my-cmp.ts --producer=myProducer --producerDirectory=apps/myProducer",
14
+ "description": "Create a federated module from myProducer, that exposes my-cmp from ./src/component/my-cmp.ts as MyModule."
11
15
  }
12
16
  ],
13
17
  "type": "object",
@@ -30,12 +34,14 @@
30
34
  },
31
35
  "remote": {
32
36
  "type": "string",
33
- "description": "The name of the remote.",
34
- "x-prompt": "What is/should the remote be named?"
37
+ "description": "The name of the Producer (remote).",
38
+ "x-prompt": "What is/should the Producer (remote) be named?",
39
+ "alias": "producer"
35
40
  },
36
41
  "remoteDirectory": {
37
- "description": "The directory of the new remote application if one needs to be created.",
38
- "type": "string"
42
+ "description": "The directory of the new Producer (remote) application if one needs to be created.",
43
+ "type": "string",
44
+ "alias": "producerDirectory"
39
45
  },
40
46
  "style": {
41
47
  "description": "The file extension to be used for style files.",
@@ -70,7 +76,7 @@
70
76
  },
71
77
  "host": {
72
78
  "type": "string",
73
- "description": "The host / shell application for this remote."
79
+ "description": "The Consumer (host) application for this Producer (remote)."
74
80
  },
75
81
  "bundler": {
76
82
  "description": "The bundler to use.",
@@ -2,8 +2,8 @@
2
2
  "$schema": "https://json-schema.org/schema",
3
3
  "$id": "GeneratorReactHost",
4
4
  "cli": "nx",
5
- "title": "Generate Module Federation Setup for React Host App",
6
- "description": "Create Module Federation configuration files for given React Host Application.",
5
+ "title": "Generate Module Federation Setup for React Consumer (Host) App",
6
+ "description": "Create Module Federation configuration files for given React Consumer (Host) Application.",
7
7
  "type": "object",
8
8
  "properties": {
9
9
  "directory": {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "name": {
20
20
  "type": "string",
21
- "description": "The name of the host application to generate the Module Federation configuration",
21
+ "description": "The name of the Consumer (host) application to generate the Module Federation configuration",
22
22
  "pattern": "^[a-zA-Z][^:]*$",
23
23
  "x-priority": "important"
24
24
  },
@@ -74,7 +74,7 @@
74
74
  },
75
75
  "dynamic": {
76
76
  "type": "boolean",
77
- "description": "Should the host application use dynamic federation?",
77
+ "description": "Should the Consumer (host) application use dynamic federation?",
78
78
  "default": false
79
79
  },
80
80
  "skipFormat": {
@@ -141,18 +141,19 @@
141
141
  },
142
142
  "remotes": {
143
143
  "type": "array",
144
- "description": "A list of remote application names that the host application should consume.",
144
+ "description": "A list of Producer (remote) application names that the Consumer (host) application should consume.",
145
145
  "default": [],
146
- "x-priority": "important"
146
+ "x-priority": "important",
147
+ "alias": "producers"
147
148
  },
148
149
  "devServerPort": {
149
150
  "type": "number",
150
- "description": "The port for the dev server of the remote app.",
151
+ "description": "The port for the dev server of the Producer (remote) app.",
151
152
  "default": 4200,
152
153
  "x-priority": "important"
153
154
  },
154
155
  "ssr": {
155
- "description": "Whether to configure SSR for the host application",
156
+ "description": "Whether to configure SSR for the Consumer (host) application",
156
157
  "type": "boolean",
157
158
  "default": false
158
159
  },
@@ -32,33 +32,36 @@ async function addRollupBuildTarget(host, options) {
32
32
  : p.plugin === '@nx/rollup/plugin');
33
33
  if (hasRollupPlugin) {
34
34
  // New behavior, using rollup config file and inferred target.
35
- host.write((0, devkit_1.joinPathFragments)(options.projectRoot, 'rollup.config.js'), (0, devkit_1.stripIndents) `
36
- const { withNx } = require('@nx/rollup/with-nx');
37
- const url = require('@rollup/plugin-url');
38
- const svg = require('@svgr/rollup');
39
-
40
- module.exports = withNx({
41
- main: '${(0, maybe_js_1.maybeJs)(options, './src/index.ts')}',
42
- outputPath: '${(0, devkit_1.joinPathFragments)((0, devkit_1.offsetFromRoot)(options.projectRoot), 'dist', options.projectRoot)}',
43
- tsConfig: './tsconfig.lib.json',
44
- compiler: '${options.compiler ?? 'babel'}',
45
- external: ${JSON.stringify(external)},
46
- format: ['esm'],
47
- assets:[{ input: '.', output: '.', glob: 'README.md'}],
48
- }, {
49
- // Provide additional rollup configuration here. See: https://rollupjs.org/configuration-options
50
- plugins: [
51
- svg({
52
- svgo: false,
53
- titleProp: true,
54
- ref: true,
55
- }),
56
- url({
57
- limit: 10000, // 10kB
58
- }),
59
- ],
60
- });
61
- `);
35
+ host.write((0, devkit_1.joinPathFragments)(options.projectRoot, 'rollup.config.cjs'), `const { withNx } = require('@nx/rollup/with-nx');
36
+ const url = require('@rollup/plugin-url');
37
+ const svg = require('@svgr/rollup');
38
+
39
+ module.exports = withNx(
40
+ {
41
+ main: '${(0, maybe_js_1.maybeJs)(options, './src/index.ts')}',
42
+ outputPath: '${options.isUsingTsSolutionConfig
43
+ ? './dist'
44
+ : (0, devkit_1.joinPathFragments)((0, devkit_1.offsetFromRoot)(options.projectRoot), 'dist', options.projectRoot)}',
45
+ tsConfig: './tsconfig.lib.json',
46
+ compiler: '${options.compiler ?? 'babel'}',
47
+ external: ${JSON.stringify(external)},
48
+ format: ['esm'],
49
+ assets:[{ input: '.', output: '.', glob: 'README.md'}],
50
+ }, {
51
+ // Provide additional rollup configuration here. See: https://rollupjs.org/configuration-options
52
+ plugins: [
53
+ svg({
54
+ svgo: false,
55
+ titleProp: true,
56
+ ref: true,
57
+ }),
58
+ url({
59
+ limit: 10000, // 10kB
60
+ }),
61
+ ],
62
+ }
63
+ );
64
+ `);
62
65
  }
63
66
  else {
64
67
  // Legacy behavior, there is a target in project.json using rollup executor.
@@ -21,6 +21,7 @@ const create_ts_config_1 = require("../../utils/create-ts-config");
21
21
  const install_common_dependencies_1 = require("./lib/install-common-dependencies");
22
22
  const set_defaults_1 = require("./lib/set-defaults");
23
23
  const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
24
+ const plugin_1 = require("@nx/js/src/utils/typescript/plugin");
24
25
  async function libraryGenerator(host, schema) {
25
26
  return await libraryGeneratorInternal(host, {
26
27
  addPlugin: false,
@@ -114,6 +115,11 @@ async function libraryGeneratorInternal(host, schema) {
114
115
  const rollupTask = await (0, add_rollup_build_target_1.addRollupBuildTarget)(host, options);
115
116
  tasks.push(rollupTask);
116
117
  }
118
+ else if (options.bundler === 'none' && options.addPlugin) {
119
+ const nxJson = (0, devkit_1.readNxJson)(host);
120
+ (0, plugin_1.ensureProjectIsExcludedFromPluginRegistrations)(nxJson, options.projectRoot);
121
+ (0, devkit_1.updateNxJson)(host, nxJson);
122
+ }
117
123
  // Set up test target
118
124
  if (options.unitTestRunner === 'jest') {
119
125
  const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/jest', versions_1.nxVersion);
@@ -24,7 +24,7 @@ function updateHostWithRemote(host, hostName, remoteName) {
24
24
  }
25
25
  else {
26
26
  // TODO(jack): Point to the nx.dev guide when ready.
27
- devkit_1.logger.warn(`Could not find configuration at ${moduleFederationConfigPath}. Did you generate this project with "@nx/react:host"?`);
27
+ devkit_1.logger.warn(`Could not find configuration at ${moduleFederationConfigPath}. Did you generate this project with "@nx/react:host" or "@nx/react:consumer"?`);
28
28
  }
29
29
  if (host.exists(appComponentPath)) {
30
30
  let sourceCode = host.read(appComponentPath).toString();
@@ -32,7 +32,7 @@ function updateHostWithRemote(host, hostName, remoteName) {
32
32
  host.write(appComponentPath, (0, devkit_1.applyChangesToString)(sourceCode, (0, ast_utils_1.addRemoteRoute)(source, (0, devkit_1.names)(remoteName))));
33
33
  }
34
34
  else {
35
- devkit_1.logger.warn(`Could not find app component at ${appComponentPath}. Did you generate this project with "@nx/react:host"?`);
35
+ devkit_1.logger.warn(`Could not find app component at ${appComponentPath}. Did you generate this project with "@nx/react:host" or "@nx/react:consumer"?`);
36
36
  }
37
37
  }
38
38
  function findAppComponentPath(host, sourceRoot) {
@@ -2,8 +2,8 @@
2
2
  "$schema": "https://json-schema.org/schema",
3
3
  "$id": "GeneratorReactRemote",
4
4
  "cli": "nx",
5
- "title": "Generate Module Federation Setup for React Remote App",
6
- "description": "Create Module Federation configuration files for given React Remote Application.",
5
+ "title": "Generate Module Federation Setup for React Producer (Remote) App",
6
+ "description": "Create Module Federation configuration files for given React Producer (Remote) Application.",
7
7
  "type": "object",
8
8
  "properties": {
9
9
  "directory": {
@@ -18,13 +18,13 @@
18
18
  },
19
19
  "name": {
20
20
  "type": "string",
21
- "description": "The name of the remote application to generate the Module Federation configuration",
21
+ "description": "The name of the Producer (remote) application to generate the Module Federation configuration",
22
22
  "pattern": "^[a-zA-Z_$][a-zA-Z_$0-9]*$",
23
23
  "x-priority": "important"
24
24
  },
25
25
  "dynamic": {
26
26
  "type": "boolean",
27
- "description": "Should the host application use dynamic federation?",
27
+ "description": "Should the Consumer (host) application use dynamic federation?",
28
28
  "default": false,
29
29
  "x-priority": "internal"
30
30
  },
@@ -147,16 +147,17 @@
147
147
  },
148
148
  "host": {
149
149
  "type": "string",
150
- "description": "The host / shell application for this remote.",
151
- "x-priority": "important"
150
+ "description": "The Consumer (host) application for this Producer (remote).",
151
+ "x-priority": "important",
152
+ "alias": "consumer"
152
153
  },
153
154
  "devServerPort": {
154
155
  "type": "number",
155
- "description": "The port for the dev server of the remote app.",
156
+ "description": "The port for the dev server of the Producer (remote) app.",
156
157
  "x-priority": "important"
157
158
  },
158
159
  "ssr": {
159
- "description": "Whether to configure SSR for the host application",
160
+ "description": "Whether to configure SSR for the Consumer (host) application",
160
161
  "type": "boolean",
161
162
  "default": false
162
163
  },
@@ -29,7 +29,10 @@ async function projectRootPath(tree, config) {
29
29
  // libs/test-lib/src/lib
30
30
  projectDir = 'lib';
31
31
  }
32
- return (0, devkit_1.joinPathFragments)(config.sourceRoot, projectDir);
32
+ else {
33
+ projectDir = '.';
34
+ }
35
+ return (0, devkit_1.joinPathFragments)(config.sourceRoot ?? config.root, projectDir);
33
36
  }
34
37
  function containsComponentDeclaration(tree, componentPath) {
35
38
  if (!tsModule) {
@@ -70,7 +73,7 @@ async function createAllStories(tree, projectName, interactionTests, js, project
70
73
  }
71
74
  });
72
75
  await Promise.all(componentPaths.map(async (componentPath) => {
73
- const relativeCmpDir = componentPath.replace((0, path_1.join)(sourceRoot, '/'), '');
76
+ const relativeCmpDir = componentPath.replace((0, path_1.join)(sourceRoot ?? root, '/'), '');
74
77
  if (!containsComponentDeclaration(tree, componentPath)) {
75
78
  return;
76
79
  }
@@ -32,8 +32,8 @@ async function storybookConfigurationGeneratorInternal(host, schema) {
32
32
  let uiFramework = '@storybook/react-vite';
33
33
  const projectConfig = (0, devkit_1.readProjectConfiguration)(host, schema.project);
34
34
  if (findWebpackConfig(host, projectConfig.root) ||
35
- projectConfig.targets['build']?.executor === '@nx/rollup:rollup' ||
36
- projectConfig.targets['build']?.executor === '@nx/expo:build') {
35
+ projectConfig.targets?.['build']?.executor === '@nx/rollup:rollup' ||
36
+ projectConfig.targets?.['build']?.executor === '@nx/expo:build') {
37
37
  uiFramework = '@storybook/react-webpack5';
38
38
  }
39
39
  if (uiFramework === '@storybook/react-vite') {
@@ -1,4 +0,0 @@
1
- import { StaticRemotesConfig } from '@nx/module-federation/src/utils';
2
- import { ExecutorContext } from '@nx/devkit';
3
- import { ModuleFederationDevServerOptions } from '../executors/module-federation-dev-server/schema';
4
- export declare function buildStaticRemotes(staticRemotesConfig: StaticRemotesConfig, nxBin: any, context: ExecutorContext, options: ModuleFederationDevServerOptions): Promise<Record<string, string>>;
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildStaticRemotes = buildStaticRemotes;
4
- const logger_1 = require("nx/src/utils/logger");
5
- const node_child_process_1 = require("node:child_process");
6
- const path_1 = require("path");
7
- const cache_directory_1 = require("nx/src/utils/cache-directory");
8
- const fs_1 = require("fs");
9
- async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options) {
10
- if (!staticRemotesConfig.remotes.length) {
11
- return;
12
- }
13
- logger_1.logger.info(`NX Building ${staticRemotesConfig.remotes.length} static remotes...`);
14
- const mappedLocationOfRemotes = {};
15
- for (const app of staticRemotesConfig.remotes) {
16
- mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig.config[app].urlSegment}`;
17
- }
18
- await new Promise((res, rej) => {
19
- const staticProcess = (0, node_child_process_1.fork)(nxBin, [
20
- 'run-many',
21
- `--target=build`,
22
- `--projects=${staticRemotesConfig.remotes.join(',')}`,
23
- ...(context.configurationName
24
- ? [`--configuration=${context.configurationName}`]
25
- : []),
26
- ...(options.parallel ? [`--parallel=${options.parallel}`] : []),
27
- ], {
28
- cwd: context.root,
29
- stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
30
- });
31
- // File to debug build failures e.g. 2024-01-01T00_00_0_0Z-build.log'
32
- const remoteBuildLogFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`);
33
- const stdoutStream = (0, fs_1.createWriteStream)(remoteBuildLogFile);
34
- staticProcess.stdout.on('data', (data) => {
35
- const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
36
- const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
37
- stdoutStream.write(stdoutString);
38
- // in addition to writing into the stdout stream, also show error directly in console
39
- // so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
40
- if (stdoutString.includes('ERROR in')) {
41
- logger_1.logger.log(stdoutString);
42
- }
43
- if (stdoutString.includes('Successfully ran target build')) {
44
- staticProcess.stdout.removeAllListeners('data');
45
- logger_1.logger.info(`NX Built ${staticRemotesConfig.remotes.length} static remotes`);
46
- res();
47
- }
48
- });
49
- staticProcess.stderr.on('data', (data) => logger_1.logger.info(data.toString()));
50
- staticProcess.once('exit', (code) => {
51
- stdoutStream.end();
52
- staticProcess.stdout.removeAllListeners('data');
53
- staticProcess.stderr.removeAllListeners('data');
54
- if (code !== 0) {
55
- rej(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
56
- }
57
- else {
58
- res();
59
- }
60
- });
61
- process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
62
- process.on('exit', () => staticProcess.kill('SIGTERM'));
63
- });
64
- return mappedLocationOfRemotes;
65
- }