@nx/react 16.9.0-beta.1 → 16.9.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/babel.d.ts +4 -3
  2. package/babel.js +2 -2
  3. package/package.json +7 -7
  4. package/src/generators/application/application.js +38 -2
  5. package/src/generators/host/files/module-federation-ssr-ts/module-federation.server.config.ts__tmpl__ +10 -0
  6. package/src/generators/host/files/module-federation-ssr-ts/server.ts__tmpl__ +28 -0
  7. package/src/generators/host/files/module-federation-ssr-ts/tsconfig.server.json__tmpl__ +15 -0
  8. package/src/generators/host/files/module-federation-ssr-ts/webpack.server.config.ts__tmpl__ +12 -0
  9. package/src/generators/host/files/module-federation-ts/module-federation.config.ts__tmpl__ +10 -0
  10. package/src/generators/host/files/module-federation-ts/src/main.ts__tmpl__ +1 -0
  11. package/src/generators/host/files/module-federation-ts/src/remotes.d.ts__tmpl__ +4 -0
  12. package/src/generators/host/files/module-federation-ts/webpack.config.prod.ts__tmpl__ +32 -0
  13. package/src/generators/host/files/module-federation-ts/webpack.config.ts__tmpl__ +12 -0
  14. package/src/generators/host/host.js +6 -2
  15. package/src/generators/host/lib/add-module-federation-files.js +14 -1
  16. package/src/generators/host/lib/setup-ssr-for-host.js +4 -1
  17. package/src/generators/host/schema.d.ts +1 -0
  18. package/src/generators/host/schema.json +5 -0
  19. package/src/generators/library/library.js +34 -2
  20. package/src/generators/remote/files/module-federation-ssr-ts/module-federation.server.config.ts__tmpl__ +10 -0
  21. package/src/generators/remote/files/module-federation-ssr-ts/server.ts__tmpl__ +45 -0
  22. package/src/generators/remote/files/module-federation-ssr-ts/webpack.server.config.ts__tmpl__ +12 -0
  23. package/src/generators/remote/files/module-federation-ts/module-federation.config.ts__tmpl__ +10 -0
  24. package/src/generators/remote/files/module-federation-ts/src/main.ts__tmpl__ +1 -0
  25. package/src/generators/remote/files/module-federation-ts/src/remote-entry.ts__tmpl__ +1 -0
  26. package/src/generators/remote/files/module-federation-ts/webpack.config.prod.ts__tmpl__ +1 -0
  27. package/src/generators/remote/files/module-federation-ts/webpack.config.ts__tmpl__ +12 -0
  28. package/src/generators/remote/lib/setup-ssr-for-remote.js +4 -1
  29. package/src/generators/remote/lib/update-host-with-remote.js +4 -1
  30. package/src/generators/remote/remote.d.ts +1 -1
  31. package/src/generators/remote/remote.js +19 -3
  32. package/src/generators/remote/schema.d.ts +6 -0
  33. package/src/generators/remote/schema.json +5 -0
  34. package/src/module-federation/utils.js +1 -1
  35. package/src/rules/update-module-federation-project.d.ts +1 -0
  36. package/src/rules/update-module-federation-project.js +2 -2
package/babel.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  interface NxReactBabelOptions {
2
+ development?: boolean;
2
3
  runtime?: string;
3
4
  importSource?: string;
4
5
  useBuiltIns?: boolean | string;
@@ -10,7 +11,7 @@ interface NxReactBabelOptions {
10
11
  loose?: boolean;
11
12
  };
12
13
  }
13
- declare function getReactPresetOptions({ presetOptions, env }: {
14
- presetOptions: any;
15
- env: any;
14
+ declare function getReactPresetOptions({ presetOptions, env, }: {
15
+ env: string;
16
+ presetOptions: NxReactBabelOptions;
16
17
  }): Record<string, string | boolean>;
package/babel.js CHANGED
@@ -33,10 +33,10 @@ module.exports = function (api, options) {
33
33
  presets,
34
34
  };
35
35
  };
36
- function getReactPresetOptions({ presetOptions, env }) {
36
+ function getReactPresetOptions({ presetOptions, env, }) {
37
37
  const reactPresetOptions = {
38
38
  runtime: presetOptions.runtime ?? 'automatic',
39
- development: env !== 'production',
39
+ development: presetOptions.development ?? env !== 'production',
40
40
  };
41
41
  // JSX spread is transformed into object spread in `@babel/plugin-transform-react-jsx`
42
42
  // `useBuiltIns` will be removed in Babel 8.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/react",
3
- "version": "16.9.0-beta.1",
3
+ "version": "16.9.0-beta.2",
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, 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": {
@@ -31,11 +31,11 @@
31
31
  "migrations": "./migrations.json"
32
32
  },
33
33
  "dependencies": {
34
- "@nrwl/react": "16.9.0-beta.1",
35
- "@nx/devkit": "16.9.0-beta.1",
36
- "@nx/js": "16.9.0-beta.1",
37
- "@nx/linter": "16.9.0-beta.1",
38
- "@nx/web": "16.9.0-beta.1",
34
+ "@nrwl/react": "16.9.0-beta.2",
35
+ "@nx/devkit": "16.9.0-beta.2",
36
+ "@nx/js": "16.9.0-beta.2",
37
+ "@nx/linter": "16.9.0-beta.2",
38
+ "@nx/web": "16.9.0-beta.2",
39
39
  "@phenomnomnominal/tsquery": "~5.0.1",
40
40
  "@svgr/webpack": "^8.0.1",
41
41
  "chalk": "^4.1.0",
@@ -47,5 +47,5 @@
47
47
  "access": "public"
48
48
  },
49
49
  "type": "commonjs",
50
- "gitHead": "5056d6cefb2949ba865019e8b71e633fba28c091"
50
+ "gitHead": "e11d538fa2c7266066d554d9405abab8e0a65040"
51
51
  }
@@ -74,7 +74,7 @@ async function applicationGeneratorInternal(host, schema) {
74
74
  (0, create_application_files_1.createApplicationFiles)(host, options);
75
75
  (0, add_project_1.addProject)(host, options);
76
76
  if (options.bundler === 'vite') {
77
- const { viteConfigurationGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
77
+ const { createOrEditViteConfig, viteConfigurationGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
78
78
  // We recommend users use `import.meta.env.MODE` and other variables in their code to differentiate between production and development.
79
79
  // See: https://vitejs.dev/guide/env-and-mode.html
80
80
  if (host.exists((0, devkit_1.joinPathFragments)(options.appProjectRoot, 'src/environments'))) {
@@ -90,6 +90,24 @@ async function applicationGeneratorInternal(host, schema) {
90
90
  skipFormat: true,
91
91
  });
92
92
  tasks.push(viteTask);
93
+ createOrEditViteConfig(host, {
94
+ project: options.projectName,
95
+ includeLib: false,
96
+ includeVitest: options.unitTestRunner === 'vitest',
97
+ inSourceTests: options.inSourceTests,
98
+ rollupOptionsExternal: [
99
+ `'react'`,
100
+ `'react-dom'`,
101
+ `'react/jsx-runtime'`,
102
+ ],
103
+ rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
104
+ imports: [
105
+ options.compiler === 'swc'
106
+ ? `import react from '@vitejs/plugin-react-swc'`
107
+ : `import react from '@vitejs/plugin-react'`,
108
+ ],
109
+ plugins: ['react()'],
110
+ }, false);
93
111
  }
94
112
  else if (options.bundler === 'webpack') {
95
113
  const { webpackInitGenerator } = (0, devkit_1.ensurePackage)('@nx/webpack', versions_1.nxVersion);
@@ -112,7 +130,7 @@ async function applicationGeneratorInternal(host, schema) {
112
130
  tasks.push(rspackTask);
113
131
  }
114
132
  if (options.bundler !== 'vite' && options.unitTestRunner === 'vitest') {
115
- const { vitestGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
133
+ const { createOrEditViteConfig, vitestGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
116
134
  const vitestTask = await vitestGenerator(host, {
117
135
  uiFramework: 'react',
118
136
  coverageProvider: 'c8',
@@ -121,6 +139,24 @@ async function applicationGeneratorInternal(host, schema) {
121
139
  skipFormat: true,
122
140
  });
123
141
  tasks.push(vitestTask);
142
+ createOrEditViteConfig(host, {
143
+ project: options.projectName,
144
+ includeLib: false,
145
+ includeVitest: true,
146
+ inSourceTests: options.inSourceTests,
147
+ rollupOptionsExternal: [
148
+ `'react'`,
149
+ `'react-dom'`,
150
+ `'react/jsx-runtime'`,
151
+ ],
152
+ rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
153
+ imports: [
154
+ options.compiler === 'swc'
155
+ ? `import react from '@vitejs/plugin-react-swc'`
156
+ : `import react from '@vitejs/plugin-react'`,
157
+ ],
158
+ plugins: ['react()'],
159
+ }, true);
124
160
  }
125
161
  if ((options.bundler === 'vite' || options.unitTestRunner === 'vitest') &&
126
162
  options.inSourceTests) {
@@ -0,0 +1,10 @@
1
+ import { ModuleFederationConfig } from '@nx/webpack';
2
+
3
+ const config: ModuleFederationConfig = {
4
+ name: '<%= projectName %>',
5
+ remotes: [
6
+ <% remotes.forEach(function(r) {%> "<%= r.fileName %>", <% }); %>
7
+ ],
8
+ };
9
+
10
+ export default config;
@@ -0,0 +1,28 @@
1
+ import * as path from 'path';
2
+ import express from 'express';
3
+ import cors from 'cors';
4
+
5
+ import { handleRequest } from './src/main.server';
6
+
7
+ const port = process.env['PORT'] || 4200;
8
+ const app = express();
9
+
10
+ const browserDist = path.join(process.cwd(), '<%= browserBuildOutputPath %>');
11
+ const indexPath = path.join(browserDist, 'index.html');
12
+
13
+ app.use(cors());
14
+
15
+ app.get(
16
+ '*.*',
17
+ express.static(browserDist, {
18
+ maxAge: '1y',
19
+ })
20
+ );
21
+
22
+ app.use('*', handleRequest(indexPath));
23
+
24
+ const server = app.listen(port, () => {
25
+ console.log(`Express server listening on http://localhost:${port}`);
26
+ });
27
+
28
+ server.on('error', console.error);
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./tsconfig.app.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../out-tsc/server",
5
+ "target": "es2019",
6
+ "types": [
7
+ "node"
8
+ ]
9
+ },
10
+ "include": [
11
+ "src/remotes.d.ts",
12
+ "src/main.server.tsx",
13
+ "server.ts"
14
+ ]
15
+ }
@@ -0,0 +1,12 @@
1
+ import {composePlugins, withNx} from '@nx/webpack';
2
+ import {withReact} from '@nx/react';
3
+ import {withModuleFederationForSSR} from '@nx/react/module-federation';
4
+
5
+ import baseConfig from './module-federation.config';
6
+
7
+ const defaultConfig = {
8
+ ...baseConfig
9
+ };
10
+
11
+ // Nx plugins for webpack to build config object from Nx options and context.
12
+ export default composePlugins(withNx(), withReact({ssr: true}), withModuleFederationForSSR(defaultConfig));
@@ -0,0 +1,10 @@
1
+ import { ModuleFederationConfig } from '@nx/webpack';
2
+
3
+ const config: ModuleFederationConfig = {
4
+ name: '<%= projectName %>',
5
+ remotes: [
6
+ <% remotes.forEach(function(r) {%> "<%= r.fileName %>", <% }); %>
7
+ ],
8
+ };
9
+
10
+ export default config;
@@ -0,0 +1 @@
1
+ import('./bootstrap');
@@ -0,0 +1,4 @@
1
+ // Declare your remote Modules here
2
+ // Example declare module 'about/Module';
3
+
4
+ <% remotes.forEach(function(r) { %>declare module '<%= r.fileName %>/Module';<% }); %>
@@ -0,0 +1,32 @@
1
+ import { composePlugins, withNx } from '@nx/webpack';
2
+ import { withReact } from '@nx/react';
3
+ import { withModuleFederation } from '@nx/react/module-federation';
4
+
5
+ import baseConfig from './module-federation.config';
6
+
7
+ const prodConfig = {
8
+ ...baseConfig,
9
+ /*
10
+ * Remote overrides for production.
11
+ * Each entry is a pair of a unique name and the URL where it is deployed.
12
+ *
13
+ * e.g.
14
+ * remotes: [
15
+ * ['app1', 'http://app1.example.com'],
16
+ * ['app2', 'http://app2.example.com'],
17
+ * ]
18
+ *
19
+ * You can also use a full path to the remoteEntry.js file if desired.
20
+ *
21
+ * remotes: [
22
+ * ['app1', 'http://example.com/path/to/app1/remoteEntry.js'],
23
+ * ['app2', 'http://example.com/path/to/app2/remoteEntry.js'],
24
+ * ]
25
+ */
26
+ remotes: [
27
+ <% remotes.forEach(function(r) {%>['<%= r.fileName %>', 'http://localhost:<%= r.port %>/'],<% }); %>
28
+ ],
29
+ };
30
+
31
+ // Nx plugins for webpack to build config object from Nx options and context.
32
+ export default composePlugins(withNx(), withReact(), withModuleFederation(prodConfig));
@@ -0,0 +1,12 @@
1
+ import {composePlugins, withNx} from '@nx/webpack';
2
+ import {withReact} from '@nx/react';
3
+ import {withModuleFederation} from '@nx/react/module-federation';
4
+
5
+ import baseConfig from './module-federation.config';
6
+
7
+ const config = {
8
+ ...baseConfig,
9
+ };
10
+
11
+ // Nx plugins for webpack to build config object from Nx options and context.
12
+ export default composePlugins(withNx(), withReact(), withModuleFederation(config));
@@ -20,7 +20,10 @@ async function hostGenerator(host, schema) {
20
20
  exports.hostGenerator = hostGenerator;
21
21
  async function hostGeneratorInternal(host, schema) {
22
22
  const tasks = [];
23
- const options = await (0, normalize_options_1.normalizeOptions)(host, schema, '@nx/react:host');
23
+ const options = {
24
+ ...(await (0, normalize_options_1.normalizeOptions)(host, schema, '@nx/react:host')),
25
+ typescriptConfiguration: schema.typescriptConfiguration ?? true,
26
+ };
24
27
  const initTask = await (0, application_1.default)(host, {
25
28
  ...options,
26
29
  // The target use-case is loading remotes as child routes, thus always enable routing.
@@ -47,6 +50,7 @@ async function hostGeneratorInternal(host, schema) {
47
50
  ssr: options.ssr,
48
51
  skipFormat: true,
49
52
  projectNameAndRootFormat: options.projectNameAndRootFormat,
53
+ typescriptConfiguration: options.typescriptConfiguration,
50
54
  });
51
55
  remotePort++;
52
56
  }
@@ -64,7 +68,7 @@ async function hostGeneratorInternal(host, schema) {
64
68
  const setupSsrForHostTask = await (0, setup_ssr_for_host_1.setupSsrForHost)(host, options, options.projectName, remotesWithPorts);
65
69
  tasks.push(setupSsrForHostTask);
66
70
  const projectConfig = (0, devkit_1.readProjectConfiguration)(host, options.projectName);
67
- projectConfig.targets.server.options.webpackConfig = (0, devkit_1.joinPathFragments)(projectConfig.root, 'webpack.server.config.js');
71
+ projectConfig.targets.server.options.webpackConfig = (0, devkit_1.joinPathFragments)(projectConfig.root, `webpack.server.config.${options.typescriptConfiguration ? 'ts' : 'js'}`);
68
72
  (0, devkit_1.updateProjectConfiguration)(host, options.projectName, projectConfig);
69
73
  }
70
74
  if (!options.skipFormat) {
@@ -20,7 +20,20 @@ function addModuleFederationFiles(host, options, defaultRemoteManifest) {
20
20
  // new entry file.
21
21
  host.rename((0, path_1.join)(options.appProjectRoot, 'src/main.tsx'), (0, path_1.join)(options.appProjectRoot, 'src/bootstrap.tsx'));
22
22
  (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `../files/common`), options.appProjectRoot, templateVariables);
23
+ const pathToModuleFederationFiles = options.typescriptConfiguration
24
+ ? 'module-federation-ts'
25
+ : 'module-federation';
23
26
  // New entry file is created here.
24
- (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `../files/module-federation`), options.appProjectRoot, templateVariables);
27
+ (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `../files/${pathToModuleFederationFiles}`), options.appProjectRoot, templateVariables);
28
+ if (options.typescriptConfiguration) {
29
+ const pathToWebpackConfig = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'webpack.config.js');
30
+ const pathToWebpackProdConfig = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'webpack.config.prod.js');
31
+ if (host.exists(pathToWebpackConfig)) {
32
+ host.delete(pathToWebpackConfig);
33
+ }
34
+ if (host.exists(pathToWebpackProdConfig)) {
35
+ host.delete(pathToWebpackProdConfig);
36
+ }
37
+ }
25
38
  }
26
39
  exports.addModuleFederationFiles = addModuleFederationFiles;
@@ -8,7 +8,10 @@ async function setupSsrForHost(tree, options, appName, defaultRemoteManifest) {
8
8
  let project = (0, devkit_1.readProjectConfiguration)(tree, appName);
9
9
  project.targets.serve.executor = '@nx/react:module-federation-ssr-dev-server';
10
10
  (0, devkit_1.updateProjectConfiguration)(tree, appName, project);
11
- (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, '../files/module-federation-ssr'), project.root, {
11
+ const pathToModuleFederationSsrFiles = options.typescriptConfiguration
12
+ ? 'module-federation-ssr-ts'
13
+ : 'module-federation-ssr';
14
+ (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, `../files/${pathToModuleFederationSsrFiles}`), project.root, {
12
15
  ...options,
13
16
  remotes: defaultRemoteManifest.map(({ name, port }) => {
14
17
  return {
@@ -24,6 +24,7 @@ export interface Schema {
24
24
  tags?: string;
25
25
  unitTestRunner: 'jest' | 'vitest' | 'none';
26
26
  minimal?: boolean;
27
+ typescriptConfiguration?: boolean;
27
28
  }
28
29
 
29
30
  export interface NormalizedSchema extends Schema {
@@ -166,6 +166,11 @@
166
166
  "description": "Generate a React app with a minimal setup. No nx starter template.",
167
167
  "type": "boolean",
168
168
  "default": false
169
+ },
170
+ "typescriptConfiguration": {
171
+ "type": "boolean",
172
+ "description": "Whether the module federation configuration and webpack configuration files should use TS.",
173
+ "default": true
169
174
  }
170
175
  },
171
176
  "required": ["name"],
@@ -50,7 +50,7 @@ async function libraryGeneratorInternal(host, schema) {
50
50
  (0, create_files_1.createFiles)(host, options);
51
51
  // Set up build target
52
52
  if (options.buildable && options.bundler === 'vite') {
53
- const { viteConfigurationGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
53
+ const { viteConfigurationGenerator, createOrEditViteConfig } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
54
54
  const viteTask = await viteConfigurationGenerator(host, {
55
55
  uiFramework: 'react',
56
56
  project: options.name,
@@ -63,6 +63,24 @@ async function libraryGeneratorInternal(host, schema) {
63
63
  testEnvironment: 'jsdom',
64
64
  });
65
65
  tasks.push(viteTask);
66
+ createOrEditViteConfig(host, {
67
+ project: options.name,
68
+ includeLib: true,
69
+ includeVitest: options.unitTestRunner === 'vitest',
70
+ inSourceTests: options.inSourceTests,
71
+ rollupOptionsExternal: [
72
+ `'react'`,
73
+ `'react-dom'`,
74
+ `'react/jsx-runtime'`,
75
+ ],
76
+ rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
77
+ imports: [
78
+ options.compiler === 'swc'
79
+ ? `import react from '@vitejs/plugin-react-swc'`
80
+ : `import react from '@vitejs/plugin-react'`,
81
+ ],
82
+ plugins: ['react()'],
83
+ }, false);
66
84
  }
67
85
  else if (options.buildable && options.bundler === 'rollup') {
68
86
  const rollupTask = await (0, add_rollup_build_target_1.addRollupBuildTarget)(host, options);
@@ -90,7 +108,7 @@ async function libraryGeneratorInternal(host, schema) {
90
108
  else if (options.unitTestRunner === 'vitest' &&
91
109
  options.bundler !== 'vite' // tests are already configured if bundler is vite
92
110
  ) {
93
- const { vitestGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
111
+ const { vitestGenerator, createOrEditViteConfig } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
94
112
  const vitestTask = await vitestGenerator(host, {
95
113
  uiFramework: 'react',
96
114
  project: options.name,
@@ -100,6 +118,20 @@ async function libraryGeneratorInternal(host, schema) {
100
118
  testEnvironment: 'jsdom',
101
119
  });
102
120
  tasks.push(vitestTask);
121
+ createOrEditViteConfig(host, {
122
+ project: options.name,
123
+ includeLib: true,
124
+ includeVitest: true,
125
+ inSourceTests: options.inSourceTests,
126
+ rollupOptionsExternal: [
127
+ `'react'`,
128
+ `'react-dom'`,
129
+ `'react/jsx-runtime'`,
130
+ ],
131
+ rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
132
+ imports: [`import react from '@vitejs/plugin-react'`],
133
+ plugins: ['react()'],
134
+ }, true);
103
135
  }
104
136
  if (options.component) {
105
137
  const componentTask = await (0, component_1.default)(host, {
@@ -0,0 +1,10 @@
1
+ import {ModuleFederationConfig} from '@nx/webpack';
2
+
3
+ const config: ModuleFederationConfig = {
4
+ name: '<%= projectName %>',
5
+ exposes: {
6
+ './Module': '<%= appProjectRoot %>/src/remote-entry.ts',
7
+ },
8
+ };
9
+
10
+ export default config;
@@ -0,0 +1,45 @@
1
+ import * as path from 'path';
2
+ import express from 'express';
3
+ import cors from 'cors';
4
+
5
+ import { handleRequest } from './src/main.server';
6
+
7
+ const port = process.env['PORT'] || 4200;
8
+ const app = express();
9
+
10
+ const browserDist = path.join(process.cwd(), '<%= browserBuildOutputPath %>');
11
+ const serverDist = path.join(process.cwd(), '<%= serverBuildOutputPath %>');
12
+ const indexPath = path.join(browserDist, 'index.html');
13
+
14
+ app.use(cors());
15
+
16
+ // Client-side static bundles
17
+ app.get(
18
+ '*.*',
19
+ express.static(browserDist, {
20
+ maxAge: '1y',
21
+ })
22
+ );
23
+
24
+ // Static bundles for server-side module federation
25
+ app.use('/server',
26
+ express.static(serverDist, {
27
+ maxAge: '1y'
28
+ })
29
+ );
30
+
31
+ app.use('*', handleRequest(indexPath));
32
+
33
+ const server = app.listen(port, () => {
34
+ console.log(`Express server listening on http://localhost:${port}`);
35
+
36
+ /**
37
+ * DO NOT REMOVE IF USING @nx/react:module-federation-dev-ssr executor
38
+ * to serve your Host application with this Remote application.
39
+ * This message allows Nx to determine when the Remote is ready to be
40
+ * consumed by the Host.
41
+ */
42
+ process.send?.('nx.server.ready');
43
+ });
44
+
45
+ server.on('error', console.error);
@@ -0,0 +1,12 @@
1
+ import {composePlugins, withNx} from '@nx/webpack';
2
+ import {withReact} from '@nx/react';
3
+ import {withModuleFederationForSSR} from '@nx/react/module-federation';
4
+
5
+ import baseConfig from "./module-federation.server.config";
6
+
7
+ const defaultConfig = {
8
+ ...baseConfig,
9
+ };
10
+
11
+ // Nx plugins for webpack to build config object from Nx options and context.
12
+ export default composePlugins(withNx(), withReact({ssr: true}), withModuleFederationForSSR(defaultConfig));
@@ -0,0 +1,10 @@
1
+ import {ModuleFederationConfig} from '@nx/webpack';
2
+
3
+ const config: ModuleFederationConfig = {
4
+ name: '<%= projectName %>',
5
+ exposes: {
6
+ './Module': './src/remote-entry.ts',
7
+ },
8
+ };
9
+
10
+ export default config;
@@ -0,0 +1 @@
1
+ import('./bootstrap');
@@ -0,0 +1 @@
1
+ export { default } from './app/app';
@@ -0,0 +1 @@
1
+ export default require('./webpack.config');
@@ -0,0 +1,12 @@
1
+ import {composePlugins, withNx} from '@nx/webpack';
2
+ import {withReact} from '@nx/react';
3
+ import {withModuleFederation} from '@nx/react/module-federation';
4
+
5
+ import baseConfig from './module-federation.config';
6
+
7
+ const config = {
8
+ ...baseConfig,
9
+ };
10
+
11
+ // Nx plugins for webpack to build config object from Nx options and context.
12
+ export default composePlugins(withNx(), withReact(), withModuleFederation(config));
@@ -6,7 +6,10 @@ const versions_1 = require("../../../utils/versions");
6
6
  async function setupSsrForRemote(tree, options, appName) {
7
7
  const tasks = [];
8
8
  const project = (0, devkit_1.readProjectConfiguration)(tree, appName);
9
- (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, '../files/module-federation-ssr'), project.root, {
9
+ const pathToModuleFederationSsrFiles = options.typescriptConfiguration
10
+ ? 'module-federation-ssr-ts'
11
+ : 'module-federation-ssr';
12
+ (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, `../files/${pathToModuleFederationSsrFiles}`), project.root, {
10
13
  ...options,
11
14
  appName,
12
15
  tmpl: '',
@@ -10,7 +10,10 @@ function updateHostWithRemote(host, hostName, remoteName) {
10
10
  tsModule = (0, ensure_typescript_1.ensureTypescript)();
11
11
  }
12
12
  const hostConfig = (0, devkit_1.readProjectConfiguration)(host, hostName);
13
- const moduleFederationConfigPath = (0, devkit_1.joinPathFragments)(hostConfig.root, 'module-federation.config.js');
13
+ let moduleFederationConfigPath = (0, devkit_1.joinPathFragments)(hostConfig.root, 'module-federation.config.js');
14
+ if (!host.exists(moduleFederationConfigPath)) {
15
+ moduleFederationConfigPath = (0, devkit_1.joinPathFragments)(hostConfig.root, 'module-federation.config.ts');
16
+ }
14
17
  const remoteDefsPath = (0, devkit_1.joinPathFragments)(hostConfig.sourceRoot, 'remotes.d.ts');
15
18
  const appComponentPath = findAppComponentPath(host, hostConfig.sourceRoot);
16
19
  if (host.exists(moduleFederationConfigPath)) {
@@ -1,7 +1,7 @@
1
1
  import { GeneratorCallback, Tree } from '@nx/devkit';
2
2
  import { NormalizedSchema } from '../application/schema';
3
3
  import { Schema } from './schema';
4
- export declare function addModuleFederationFiles(host: Tree, options: NormalizedSchema): void;
4
+ export declare function addModuleFederationFiles(host: Tree, options: NormalizedSchema<Schema>): void;
5
5
  export declare function remoteGenerator(host: Tree, schema: Schema): Promise<GeneratorCallback>;
6
6
  export declare function remoteGeneratorInternal(host: Tree, schema: Schema): Promise<GeneratorCallback>;
7
7
  export default remoteGenerator;
@@ -15,7 +15,20 @@ function addModuleFederationFiles(host, options) {
15
15
  ...options,
16
16
  tmpl: '',
17
17
  };
18
- (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `./files/module-federation`), options.appProjectRoot, templateVariables);
18
+ const pathToModuleFederationFiles = options.typescriptConfiguration
19
+ ? 'module-federation-ts'
20
+ : 'module-federation';
21
+ (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `./files/${pathToModuleFederationFiles}`), options.appProjectRoot, templateVariables);
22
+ if (options.typescriptConfiguration) {
23
+ const pathToWebpackConfig = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'webpack.config.js');
24
+ const pathToWebpackProdConfig = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'webpack.config.prod.js');
25
+ if (host.exists(pathToWebpackConfig)) {
26
+ host.delete(pathToWebpackConfig);
27
+ }
28
+ if (host.exists(pathToWebpackProdConfig)) {
29
+ host.delete(pathToWebpackProdConfig);
30
+ }
31
+ }
19
32
  }
20
33
  exports.addModuleFederationFiles = addModuleFederationFiles;
21
34
  async function remoteGenerator(host, schema) {
@@ -27,7 +40,10 @@ async function remoteGenerator(host, schema) {
27
40
  exports.remoteGenerator = remoteGenerator;
28
41
  async function remoteGeneratorInternal(host, schema) {
29
42
  const tasks = [];
30
- const options = await (0, normalize_options_1.normalizeOptions)(host, schema, '@nx/react:remote');
43
+ const options = {
44
+ ...(await (0, normalize_options_1.normalizeOptions)(host, schema, '@nx/react:remote')),
45
+ typescriptConfiguration: schema.typescriptConfiguration ?? true,
46
+ };
31
47
  const initAppTask = await (0, application_1.default)(host, {
32
48
  ...options,
33
49
  // Only webpack works with module federation for now.
@@ -54,7 +70,7 @@ async function remoteGeneratorInternal(host, schema) {
54
70
  const setupSsrForRemoteTask = await (0, setup_ssr_for_remote_1.setupSsrForRemote)(host, options, options.projectName);
55
71
  tasks.push(setupSsrForRemoteTask);
56
72
  const projectConfig = (0, devkit_1.readProjectConfiguration)(host, options.projectName);
57
- projectConfig.targets.server.options.webpackConfig = (0, devkit_1.joinPathFragments)(projectConfig.root, 'webpack.server.config.js');
73
+ projectConfig.targets.server.options.webpackConfig = (0, devkit_1.joinPathFragments)(projectConfig.root, `webpack.server.config.${options.typescriptConfiguration ? 'ts' : 'js'}`);
58
74
  (0, devkit_1.updateProjectConfiguration)(host, options.projectName, projectConfig);
59
75
  }
60
76
  if (!options.skipFormat) {
@@ -1,6 +1,7 @@
1
1
  import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils';
2
2
  import type { Linter } from '@nx/linter';
3
3
  import type { SupportedStyles } from '../../../typings';
4
+ import type { NormalizedSchema as ApplicationNormalizedSchema } from '../application/schema';
4
5
 
5
6
  export interface Schema {
6
7
  classComponent?: boolean;
@@ -24,4 +25,9 @@ export interface Schema {
24
25
  style: SupportedStyles;
25
26
  tags?: string;
26
27
  unitTestRunner: 'jest' | 'vitest' | 'none';
28
+ typescriptConfiguration?: boolean;
29
+ }
30
+
31
+ export interface NormalizedSchema extends ApplicationNormalizedSchema {
32
+ typescriptConfiguration: boolean;
27
33
  }
@@ -164,6 +164,11 @@
164
164
  "description": "Whether to configure SSR for the host application",
165
165
  "type": "boolean",
166
166
  "default": false
167
+ },
168
+ "typescriptConfiguration": {
169
+ "type": "boolean",
170
+ "description": "Whether the module federation configuration and webpack configuration files should use TS.",
171
+ "default": true
167
172
  }
168
173
  },
169
174
  "required": ["name"],
@@ -41,7 +41,7 @@ async function getModuleFederationConfig(mfConfig, options = { isServer: false }
41
41
  const sharedLibraries = (0, module_federation_1.shareWorkspaceLibraries)(dependencies.workspaceLibraries);
42
42
  const npmPackages = (0, module_federation_1.sharePackages)(dependencies.npmPackages);
43
43
  const sharedDependencies = {
44
- ...sharedLibraries.getLibraries(),
44
+ ...sharedLibraries.getLibraries(project.root),
45
45
  ...npmPackages,
46
46
  };
47
47
  (0, module_federation_1.applySharedFunction)(sharedDependencies, mfConfig.shared);
@@ -3,4 +3,5 @@ export declare function updateModuleFederationProject(host: Tree, options: {
3
3
  projectName: string;
4
4
  appProjectRoot: string;
5
5
  devServerPort?: number;
6
+ typescriptConfiguration?: boolean;
6
7
  }): GeneratorCallback;
@@ -8,11 +8,11 @@ function updateModuleFederationProject(host, options) {
8
8
  projectConfig.targets.build.options = {
9
9
  ...projectConfig.targets.build.options,
10
10
  main: `${options.appProjectRoot}/src/main.ts`,
11
- webpackConfig: `${options.appProjectRoot}/webpack.config.js`,
11
+ webpackConfig: `${options.appProjectRoot}/webpack.config.${options.typescriptConfiguration ? 'ts' : 'js'}`,
12
12
  };
13
13
  projectConfig.targets.build.configurations.production = {
14
14
  ...projectConfig.targets.build.configurations.production,
15
- webpackConfig: `${options.appProjectRoot}/webpack.config.prod.js`,
15
+ webpackConfig: `${options.appProjectRoot}/webpack.config.prod.${options.typescriptConfiguration ? 'ts' : 'js'}`,
16
16
  };
17
17
  projectConfig.targets.serve.executor =
18
18
  '@nx/react:module-federation-dev-server';