@nx/react 21.0.0-beta.1 → 21.0.0-beta.11

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 (114) hide show
  1. package/index.d.ts +1 -1
  2. package/index.js +1 -2
  3. package/migrations.json +6 -38
  4. package/package.json +6 -6
  5. package/plugins/component-testing/index.js +1 -1
  6. package/plugins/nx-react-webpack-plugin/lib/apply-react-config.js +3 -21
  7. package/plugins/with-react.d.ts +4 -0
  8. package/router-plugin.d.ts +1 -0
  9. package/router-plugin.js +5 -0
  10. package/src/executors/module-federation-dev-server/schema.json +1 -0
  11. package/src/executors/module-federation-ssr-dev-server/schema.json +1 -0
  12. package/src/executors/module-federation-static-server/schema.json +1 -0
  13. package/src/generators/application/application.js +52 -15
  14. package/src/generators/application/files/react-router-ssr/common/app/app-nav.tsx__tmpl__ +14 -0
  15. package/src/generators/application/files/react-router-ssr/common/app/entry.client.tsx__tmpl__ +18 -0
  16. package/src/generators/application/files/react-router-ssr/common/app/entry.server.tsx__tmpl__ +74 -0
  17. package/src/generators/application/files/react-router-ssr/common/app/root.tsx__tmpl__ +51 -0
  18. package/src/generators/application/files/react-router-ssr/common/app/routes/about.tsx__tmpl__ +7 -0
  19. package/src/generators/application/files/react-router-ssr/common/app/routes.tsx__tmpl__ +6 -0
  20. package/src/generators/application/files/react-router-ssr/common/public/favicon.ico +0 -0
  21. package/src/generators/application/files/react-router-ssr/common/react-router.config.ts__tmpl__ +5 -0
  22. package/src/generators/application/files/react-router-ssr/common/tests/routes/_index.spec.tsx__tmpl__ +16 -0
  23. package/src/generators/application/files/react-router-ssr/common/tsconfig.app.json__tmpl__ +23 -0
  24. package/src/generators/application/files/react-router-ssr/common/tsconfig.json__tmpl__ +27 -0
  25. package/src/generators/application/files/react-router-ssr/non-root/.gitignore__tmpl__ +5 -0
  26. package/src/generators/application/files/react-router-ssr/non-root/package.json__tmpl__ +24 -0
  27. package/src/generators/application/files/react-router-ssr/nx-welcome/claimed/app/nx-welcome.tsx__tmpl__ +866 -0
  28. package/src/generators/application/files/react-router-ssr/nx-welcome/not-configured/app/nx-welcome.tsx__tmpl__ +866 -0
  29. package/src/generators/application/files/react-router-ssr/nx-welcome/unclaimed/app/nx-welcome.tsx__tmpl__ +864 -0
  30. package/src/generators/application/files/react-router-ssr/ts-solution/package.json__tmpl__ +24 -0
  31. package/src/generators/application/files/react-router-ssr/ts-solution/tsconfig.app.json__tmpl__ +39 -0
  32. package/src/generators/application/lib/add-e2e.js +38 -71
  33. package/src/generators/application/lib/add-jest.js +26 -2
  34. package/src/generators/application/lib/add-linting.d.ts +1 -0
  35. package/src/generators/application/lib/add-linting.js +39 -1
  36. package/src/generators/application/lib/add-project.js +31 -15
  37. package/src/generators/application/lib/add-routing.js +1 -1
  38. package/src/generators/application/lib/bundlers/add-rspack.d.ts +0 -1
  39. package/src/generators/application/lib/bundlers/add-rspack.js +0 -18
  40. package/src/generators/application/lib/bundlers/add-vite.js +15 -6
  41. package/src/generators/application/lib/create-application-files.d.ts +61 -0
  42. package/src/generators/application/lib/create-application-files.js +81 -39
  43. package/src/generators/application/lib/get-app-tests.js +3 -3
  44. package/src/generators/application/lib/install-common-dependencies.js +13 -2
  45. package/src/generators/application/lib/normalize-options.d.ts +0 -2
  46. package/src/generators/application/lib/normalize-options.js +14 -20
  47. package/src/generators/application/schema.d.ts +5 -1
  48. package/src/generators/application/schema.json +10 -1
  49. package/src/generators/component-test/component-test.js +1 -1
  50. package/src/generators/cypress-component-configuration/lib/add-files.d.ts +1 -1
  51. package/src/generators/cypress-component-configuration/lib/add-files.js +7 -4
  52. package/src/generators/host/files/rspack-module-federation/rspack.config.js__tmpl__ +37 -13
  53. package/src/generators/host/files/rspack-module-federation/rspack.config.prod.js__tmpl__ +60 -32
  54. package/src/generators/host/files/rspack-module-federation-ssr/module-federation.server.config.js__tmpl__ +6 -0
  55. package/src/generators/host/files/rspack-module-federation-ssr/rspack.config.js__tmpl__ +66 -0
  56. package/src/generators/host/files/rspack-module-federation-ssr/server.ts__tmpl__ +1 -1
  57. package/src/generators/host/files/rspack-module-federation-ssr/src/main.server.tsx__tmpl__ +49 -0
  58. package/src/generators/host/files/rspack-module-federation-ssr-ts/module-federation.server.config.ts__tmpl__ +6 -0
  59. package/src/generators/host/files/rspack-module-federation-ssr-ts/rspack.config.ts__tmpl__ +66 -0
  60. package/src/generators/host/files/rspack-module-federation-ssr-ts/server.ts__tmpl__ +1 -1
  61. package/src/generators/host/files/rspack-module-federation-ssr-ts/src/main.server.tsx__tmpl__ +49 -0
  62. package/src/generators/host/files/rspack-module-federation-ts/rspack.config.prod.ts__tmpl__ +37 -9
  63. package/src/generators/host/files/rspack-module-federation-ts/rspack.config.ts__tmpl__ +37 -14
  64. package/src/generators/host/host.js +21 -18
  65. package/src/generators/host/lib/add-module-federation-files.js +28 -12
  66. package/src/generators/host/lib/normalize-host-name.d.ts +2 -0
  67. package/src/generators/host/lib/normalize-host-name.js +12 -0
  68. package/src/generators/host/lib/setup-ssr-for-host.d.ts +3 -3
  69. package/src/generators/host/lib/setup-ssr-for-host.js +46 -22
  70. package/src/generators/init/init.js +23 -0
  71. package/src/generators/init/schema.d.ts +2 -0
  72. package/src/generators/library/lib/add-linting.js +1 -1
  73. package/src/generators/library/lib/add-rollup-build-target.d.ts +3 -1
  74. package/src/generators/library/lib/add-rollup-build-target.js +6 -7
  75. package/src/generators/library/lib/create-files.js +2 -1
  76. package/src/generators/library/lib/normalize-options.js +8 -5
  77. package/src/generators/library/library.js +44 -30
  78. package/src/generators/library/schema.d.ts +2 -0
  79. package/src/generators/library/schema.json +8 -4
  80. package/src/generators/remote/files/rspack-module-federation/rspack.config.js__tmpl__ +40 -13
  81. package/src/generators/remote/files/rspack-module-federation-ssr/module-federation.server.config.js__tmpl__ +6 -0
  82. package/src/generators/remote/files/rspack-module-federation-ssr/rspack.config.js__tmpl__ +69 -0
  83. package/src/generators/remote/files/rspack-module-federation-ssr/server.ts__tmpl__ +2 -2
  84. package/src/generators/remote/files/rspack-module-federation-ssr/src/main.server.tsx__tmpl__ +45 -0
  85. package/src/generators/remote/files/rspack-module-federation-ssr-ts/module-federation.server.config.ts__tmpl__ +6 -0
  86. package/src/generators/remote/files/rspack-module-federation-ssr-ts/rspack.config.ts__tmpl__ +69 -0
  87. package/src/generators/remote/files/rspack-module-federation-ssr-ts/server.ts__tmpl__ +2 -2
  88. package/src/generators/remote/files/rspack-module-federation-ssr-ts/src/main.server.tsx__tmpl__ +45 -0
  89. package/src/generators/remote/files/rspack-module-federation-ts/rspack.config.ts__tmpl__ +40 -13
  90. package/src/generators/remote/lib/setup-ssr-for-remote.d.ts +1 -1
  91. package/src/generators/remote/lib/setup-ssr-for-remote.js +37 -15
  92. package/src/generators/remote/remote.js +46 -30
  93. package/src/migrations/update-21-0-0/update-babel-loose.d.ts +2 -0
  94. package/src/migrations/update-21-0-0/update-babel-loose.js +30 -0
  95. package/src/plugins/router-plugin.d.ts +10 -0
  96. package/src/plugins/router-plugin.js +221 -0
  97. package/src/rules/update-module-federation-project.d.ts +2 -1
  98. package/src/rules/update-module-federation-project.js +28 -47
  99. package/src/utils/assertion.d.ts +2 -0
  100. package/src/utils/assertion.js +6 -0
  101. package/src/utils/ast-utils.d.ts +1 -1
  102. package/src/utils/ast-utils.js +2 -2
  103. package/src/utils/ct-utils.d.ts +1 -1
  104. package/src/utils/testing-generators.js +1 -2
  105. package/src/utils/versions.d.ts +6 -4
  106. package/src/utils/versions.js +9 -6
  107. package/src/generators/host/files/rspack-module-federation-ssr/rspack.server.config.js__tmpl__ +0 -16
  108. package/src/generators/host/files/rspack-module-federation-ssr-ts/rspack.server.config.ts__tmpl__ +0 -16
  109. package/src/generators/remote/files/rspack-module-federation-ssr/rspack.server.config.js__tmpl__ +0 -16
  110. package/src/generators/remote/files/rspack-module-federation-ssr-ts/rspack.server.config.ts__tmpl__ +0 -16
  111. package/src/migrations/update-18-1-1/fix-target-defaults-inputs.d.ts +0 -2
  112. package/src/migrations/update-18-1-1/fix-target-defaults-inputs.js +0 -53
  113. package/src/utils/format-file.d.ts +0 -1
  114. package/src/utils/format-file.js +0 -11
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDefaultTemplateVariables = getDefaultTemplateVariables;
4
+ exports.createNxRspackPluginOptions = createNxRspackPluginOptions;
3
5
  exports.createApplicationFiles = createApplicationFiles;
4
6
  const devkit_1 = require("@nx/devkit");
5
7
  const js_1 = require("@nx/js");
@@ -12,6 +14,53 @@ const get_app_tests_1 = require("./get-app-tests");
12
14
  const onboarding_1 = require("nx/src/nx-cloud/utilities/onboarding");
13
15
  const has_rspack_plugin_1 = require("../../../utils/has-rspack-plugin");
14
16
  const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
17
+ const versions_1 = require("../../../utils/versions");
18
+ function getDefaultTemplateVariables(host, options) {
19
+ const hasStyleFile = ['scss', 'css', 'less'].includes(options.style);
20
+ const appTests = (0, get_app_tests_1.getAppTests)(options);
21
+ return {
22
+ ...options.names,
23
+ ...options,
24
+ typesNodeVersion: versions_1.typesNodeVersion,
25
+ typesReactDomVersion: versions_1.typesReactDomVersion,
26
+ reactRouterVersion: versions_1.reactRouterVersion,
27
+ typesReactVersion: versions_1.typesReactVersion,
28
+ reactDomVersion: versions_1.reactDomVersion,
29
+ reactVersion: versions_1.reactVersion,
30
+ reactRouterIsBotVersion: versions_1.reactRouterIsBotVersion,
31
+ js: !!options.js, // Ensure this is defined in template
32
+ tmpl: '',
33
+ offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.appProjectRoot),
34
+ appTests,
35
+ inSourceVitestTests: (0, get_in_source_vitest_tests_template_1.getInSourceVitestTestsTemplate)(appTests),
36
+ style: options.style === 'tailwind' ? 'css' : options.style,
37
+ hasStyleFile,
38
+ isUsingTsSolutionSetup: (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host),
39
+ };
40
+ }
41
+ function createNxRspackPluginOptions(options, rootOffset, tsx = true) {
42
+ return {
43
+ target: 'web',
44
+ outputPath: options.isUsingTsSolutionConfig
45
+ ? 'dist'
46
+ : (0, devkit_1.joinPathFragments)(rootOffset, 'dist', options.appProjectRoot != '.'
47
+ ? options.appProjectRoot
48
+ : options.projectName),
49
+ index: './src/index.html',
50
+ baseHref: '/',
51
+ main: (0, maybe_js_1.maybeJs)({
52
+ js: options.js,
53
+ useJsx: true,
54
+ }, `./src/main.${tsx ? 'tsx' : 'ts'}`),
55
+ tsConfig: './tsconfig.app.json',
56
+ assets: ['./src/favicon.ico', './src/assets'],
57
+ styles: options.styledModule || !options.hasStyles
58
+ ? []
59
+ : [
60
+ `./src/styles.${options.style !== 'tailwind' ? options.style : 'css'}`,
61
+ ],
62
+ };
63
+ }
15
64
  async function createApplicationFiles(host, options) {
16
65
  let styleSolutionSpecificAppFiles;
17
66
  if (options.styledModule && options.style !== 'styled-jsx') {
@@ -32,27 +81,17 @@ async function createApplicationFiles(host, options) {
32
81
  else {
33
82
  styleSolutionSpecificAppFiles = '../files/style-css-module';
34
83
  }
35
- const hasStyleFile = ['scss', 'css', 'less'].includes(options.style);
36
84
  const onBoardingStatus = await (0, onboarding_1.createNxCloudOnboardingURLForWelcomeApp)(host, options.nxCloudToken);
37
85
  const connectCloudUrl = onBoardingStatus === 'unclaimed' &&
38
86
  (await (0, onboarding_1.getNxCloudAppOnBoardingUrl)(options.nxCloudToken));
39
87
  const relativePathToRootTsConfig = (0, js_1.getRelativePathToRootTsConfig)(host, options.appProjectRoot);
40
- const appTests = (0, get_app_tests_1.getAppTests)(options);
41
- const templateVariables = {
42
- ...(0, devkit_1.names)(options.name),
43
- ...options,
44
- js: !!options.js, // Ensure this is defined in template
45
- tmpl: '',
46
- offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.appProjectRoot),
47
- appTests,
48
- inSourceVitestTests: (0, get_in_source_vitest_tests_template_1.getInSourceVitestTestsTemplate)(appTests),
49
- style: options.style === 'tailwind' ? 'css' : options.style,
50
- hasStyleFile,
51
- isUsingTsSolutionSetup: (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host),
52
- };
53
- if (options.bundler === 'vite') {
88
+ const templateVariables = getDefaultTemplateVariables(host, options);
89
+ if (options.bundler === 'vite' && !options.useReactRouter) {
54
90
  (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/base-vite'), options.appProjectRoot, templateVariables);
55
91
  }
92
+ else if (options.bundler === 'vite' && options.useReactRouter) {
93
+ generateReactRouterFiles(host, options, templateVariables);
94
+ }
56
95
  else if (options.bundler === 'webpack') {
57
96
  (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/base-webpack'), options.appProjectRoot, {
58
97
  ...templateVariables,
@@ -137,9 +176,12 @@ async function createApplicationFiles(host, options) {
137
176
  const tutorialUrl = options.rootProject
138
177
  ? 'https://nx.dev/getting-started/tutorials/react-standalone-tutorial'
139
178
  : 'https://nx.dev/react-tutorial/1-code-generation?utm_source=nx-project';
140
- (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, '../files/nx-welcome', onBoardingStatus), options.appProjectRoot, { ...templateVariables, connectCloudUrl, tutorialUrl });
179
+ const path = options.useReactRouter
180
+ ? '../files/react-router-ssr/nx-welcome'
181
+ : '../files/nx-welcome';
182
+ (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, path, onBoardingStatus), options.appProjectRoot, { ...templateVariables, connectCloudUrl, tutorialUrl });
141
183
  }
142
- (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, styleSolutionSpecificAppFiles), options.appProjectRoot, templateVariables);
184
+ (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, styleSolutionSpecificAppFiles, options.useReactRouter ? 'src' : ''), options.appProjectRoot, templateVariables);
143
185
  if (options.js) {
144
186
  (0, devkit_1.toJS)(host, {
145
187
  useJsx: options.bundler === 'vite' || options.bundler === 'rspack',
@@ -171,26 +213,26 @@ function createNxWebpackPluginOptions(options, rootOffset) {
171
213
  ],
172
214
  };
173
215
  }
174
- function createNxRspackPluginOptions(options, rootOffset) {
175
- return {
176
- target: 'web',
177
- outputPath: options.isUsingTsSolutionConfig
178
- ? 'dist'
179
- : (0, devkit_1.joinPathFragments)(rootOffset, 'dist', options.appProjectRoot != '.'
180
- ? options.appProjectRoot
181
- : options.projectName),
182
- index: './src/index.html',
183
- baseHref: '/',
184
- main: (0, maybe_js_1.maybeJs)({
185
- js: options.js,
186
- useJsx: true,
187
- }, `./src/main.tsx`),
188
- tsConfig: './tsconfig.app.json',
189
- assets: ['./src/favicon.ico', './src/assets'],
190
- styles: options.styledModule || !options.hasStyles
191
- ? []
192
- : [
193
- `./src/styles.${options.style !== 'tailwind' ? options.style : 'css'}`,
194
- ],
195
- };
216
+ function generateReactRouterFiles(tree, options, templateVariables) {
217
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, '../files/react-router-ssr/common'), options.appProjectRoot, templateVariables);
218
+ if (options.rootProject) {
219
+ const gitignore = tree.read('.gitignore', 'utf-8');
220
+ tree.write('.gitignore', `${gitignore}\n.cache\nbuild\npublic/build\n.env\n\.react-router\n`);
221
+ }
222
+ else {
223
+ (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, '../files/react-router-ssr/non-root'), options.appProjectRoot, templateVariables);
224
+ }
225
+ if (options.isUsingTsSolutionConfig) {
226
+ (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, '../files/react-router-ssr/ts-solution'), options.appProjectRoot, templateVariables);
227
+ (0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'package.json'), (json) => {
228
+ if (options.projectName !== options.importPath) {
229
+ json.nx = { name: options.projectName };
230
+ }
231
+ if (options.parsedTags?.length) {
232
+ json.nx ??= {};
233
+ json.nx.tags = options.parsedTags;
234
+ }
235
+ return json;
236
+ });
237
+ }
196
238
  }
@@ -11,9 +11,9 @@ function getAppTests(options) {
11
11
 
12
12
  it('should have a greeting as the title', () => {
13
13
  ${options.routing
14
- ? 'const { getByText } = render(<BrowserRouter><App /></BrowserRouter>);'
15
- : 'const { getByText } = render(<App />);'}
16
- expect(getByText(new RegExp('Welcome ${options.projectName}', 'gi'))).toBeTruthy();
14
+ ? 'const { getAllByText } = render(<BrowserRouter><App /></BrowserRouter>);'
15
+ : 'const { getAllByText } = render(<App />);'}
16
+ expect(getAllByText(new RegExp('Welcome ${options.projectName}', 'gi')).length > 0).toBeTruthy();
17
17
  });
18
18
  `;
19
19
  }
@@ -11,13 +11,24 @@ async function installCommonDependencies(host, options) {
11
11
  const reactDeps = await (0, version_utils_1.getReactDependenciesVersionsToInstall)(host);
12
12
  const dependencies = {};
13
13
  const devDependencies = {
14
- '@types/node': versions_1.typesNodeVersion,
15
14
  '@types/react': reactDeps['@types/react'],
16
15
  '@types/react-dom': reactDeps['@types/react-dom'],
16
+ '@types/node': versions_1.typesNodeVersion,
17
+ ...(options.useReactRouter
18
+ ? {
19
+ '@react-router/dev': versions_1.reactRouterVersion,
20
+ }
21
+ : {}),
17
22
  };
18
23
  if (options.bundler !== 'vite') {
19
24
  dependencies['tslib'] = versions_1.tsLibVersion;
20
25
  }
26
+ if (options.useReactRouter) {
27
+ dependencies['react-router'] = versions_1.reactRouterVersion;
28
+ dependencies['@react-router/node'] = versions_1.reactRouterVersion;
29
+ dependencies['@react-router/serve'] = versions_1.reactRouterVersion;
30
+ dependencies['isbot'] = versions_1.reactRouterIsBotVersion;
31
+ }
21
32
  // Vite requires style preprocessors to be installed manually.
22
33
  // `@nx/webpack` installs them automatically for now.
23
34
  if (options.bundler === 'vite' || options.unitTestRunner === 'vitest') {
@@ -45,5 +56,5 @@ async function installCommonDependencies(host, options) {
45
56
  devDependencies['@testing-library/react'] = versions_1.testingLibraryReactVersion;
46
57
  devDependencies['@testing-library/dom'] = versions_1.testingLibraryDomVersion;
47
58
  }
48
- return (0, devkit_1.addDependenciesToPackageJson)(host, {}, devDependencies);
59
+ return (0, devkit_1.addDependenciesToPackageJson)(host, dependencies, devDependencies);
49
60
  }
@@ -1,5 +1,3 @@
1
1
  import { Tree } from '@nx/devkit';
2
2
  import { NormalizedSchema, Schema } from '../schema';
3
- export declare function normalizeDirectory(options: Schema): string;
4
- export declare function normalizeProjectName(options: Schema): string;
5
3
  export declare function normalizeOptions<T extends Schema = Schema>(host: Tree, options: Schema): Promise<NormalizedSchema<T>>;
@@ -1,27 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.normalizeDirectory = normalizeDirectory;
4
- exports.normalizeProjectName = normalizeProjectName;
5
3
  exports.normalizeOptions = normalizeOptions;
6
4
  const devkit_1 = require("@nx/devkit");
7
5
  const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
8
6
  const assertion_1 = require("../../../utils/assertion");
9
7
  const find_free_port_1 = require("./find-free-port");
10
8
  const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
11
- const get_import_path_1 = require("@nx/js/src/utils/get-import-path");
12
- function normalizeDirectory(options) {
13
- options.directory = options.directory?.replace(/\\{1,2}/g, '/');
14
- const { projectDirectory } = (0, devkit_1.extractLayoutDirectory)(options.directory);
15
- return projectDirectory
16
- ? `${(0, devkit_1.names)(projectDirectory).fileName}/${(0, devkit_1.names)(options.name).fileName}`
17
- : (0, devkit_1.names)(options.name).fileName;
18
- }
19
- function normalizeProjectName(options) {
20
- return normalizeDirectory(options).replace(new RegExp('/', 'g'), '-');
21
- }
22
9
  async function normalizeOptions(host, options) {
23
- await (0, project_name_and_root_utils_1.ensureProjectName)(host, options, 'application');
24
- const { projectName: appProjectName, projectRoot: appProjectRoot } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
10
+ await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'application');
11
+ const { projectName, names: projectNames, projectRoot: appProjectRoot, importPath, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
25
12
  name: options.name,
26
13
  projectType: 'application',
27
14
  directory: options.directory,
@@ -32,6 +19,8 @@ async function normalizeOptions(host, options) {
32
19
  nxJson.useInferencePlugins !== false;
33
20
  options.addPlugin ??= addPlugin;
34
21
  options.rootProject = appProjectRoot === '.';
22
+ const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host);
23
+ const appProjectName = !isUsingTsSolutionConfig || options.name ? projectName : importPath;
35
24
  const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
36
25
  const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
37
26
  const parsedTags = options.tags
@@ -42,23 +31,28 @@ async function normalizeOptions(host, options) {
42
31
  ? null
43
32
  : options.style;
44
33
  (0, assertion_1.assertValidStyle)(options.style);
45
- const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host);
34
+ (0, assertion_1.assertValidReactRouter)(options.useReactRouter, options.bundler);
35
+ if (options.useReactRouter && !options.bundler) {
36
+ options.bundler = 'vite';
37
+ }
38
+ options.useReactRouter = options.routing ? options.useReactRouter : false;
46
39
  const normalized = {
47
40
  ...options,
48
- name: appProjectName,
49
- projectName: isUsingTsSolutionConfig
50
- ? (0, get_import_path_1.getImportPath)(host, appProjectName)
51
- : appProjectName,
41
+ projectName: appProjectName,
52
42
  appProjectRoot,
43
+ importPath,
53
44
  e2eProjectName,
54
45
  e2eProjectRoot,
55
46
  parsedTags,
56
47
  fileName,
57
48
  styledModule,
58
49
  hasStyles: options.style !== 'none',
50
+ names: (0, devkit_1.names)(projectNames.projectSimpleName),
59
51
  isUsingTsSolutionConfig,
52
+ useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
60
53
  };
61
54
  normalized.routing = normalized.routing ?? false;
55
+ normalized.useReactRouter = normalized.useReactRouter ?? false;
62
56
  normalized.strict = normalized.strict ?? true;
63
57
  normalized.classComponent = normalized.classComponent ?? false;
64
58
  normalized.compiler = normalized.compiler ?? 'babel';
@@ -1,3 +1,4 @@
1
+ import type { names } from '@nx/devkit';
1
2
  import type { Linter, LinterType } from '@nx/eslint';
2
3
  import type { SupportedStyles } from '../../../typings/style';
3
4
 
@@ -13,6 +14,7 @@ export interface Schema {
13
14
  linter: Linter | LinterType;
14
15
  classComponent?: boolean;
15
16
  routing?: boolean;
17
+ useReactRouter?: boolean;
16
18
  skipNxJson?: boolean;
17
19
  js?: boolean;
18
20
  globalCss?: boolean;
@@ -30,7 +32,7 @@ export interface Schema {
30
32
  nxCloudToken?: string;
31
33
  useTsSolution?: boolean;
32
34
  formatter?: 'prettier' | 'none';
33
- alwaysGenerateProjectJson?: boolean; // this is needed for MF currently
35
+ useProjectJson?: boolean;
34
36
  }
35
37
 
36
38
  export interface NormalizedSchema<T extends Schema = Schema> extends T {
@@ -38,11 +40,13 @@ export interface NormalizedSchema<T extends Schema = Schema> extends T {
38
40
  appProjectRoot: string;
39
41
  e2eProjectName: string;
40
42
  e2eProjectRoot: string;
43
+ importPath: string;
41
44
  parsedTags: string[];
42
45
  fileName: string;
43
46
  styledModule: null | SupportedStyles;
44
47
  hasStyles: boolean;
45
48
  unitTestRunner: 'jest' | 'vitest' | 'none';
46
49
  addPlugin?: boolean;
50
+ names: ReturnType<typeof names>;
47
51
  isUsingTsSolutionConfig?: boolean;
48
52
  }
@@ -83,7 +83,12 @@
83
83
  "routing": {
84
84
  "type": "boolean",
85
85
  "description": "Generate application with routes.",
86
- "x-prompt": "Would you like to add React Router to this application?",
86
+ "x-prompt": "Would you like to add routing to this application?",
87
+ "default": false
88
+ },
89
+ "useReactRouter": {
90
+ "description": "Use React Router for routing.",
91
+ "type": "boolean",
87
92
  "default": false
88
93
  },
89
94
  "skipFormat": {
@@ -187,6 +192,10 @@
187
192
  "description": "Generate a React app with a minimal setup, no separate test files.",
188
193
  "type": "boolean",
189
194
  "default": false
195
+ },
196
+ "useProjectJson": {
197
+ "type": "boolean",
198
+ "description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
190
199
  }
191
200
  },
192
201
  "required": ["directory"],
@@ -10,7 +10,7 @@ const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescri
10
10
  let tsModule;
11
11
  async function componentTestGenerator(tree, options) {
12
12
  (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
13
- const { assertMinimumCypressVersion } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/cypress-version'));
13
+ const { assertMinimumCypressVersion } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/versions'));
14
14
  assertMinimumCypressVersion(10);
15
15
  // normalize any windows paths
16
16
  options.componentPath = options.componentPath.replace(/\\/g, '/');
@@ -1,4 +1,4 @@
1
+ import type { FoundTarget } from '@nx/cypress/src/utils/find-target-options';
1
2
  import { ProjectConfiguration, Tree } from '@nx/devkit';
2
3
  import type { CypressComponentConfigurationSchema } from '../schema';
3
- import { FoundTarget } from '@nx/cypress/src/utils/find-target-options';
4
4
  export declare function addFiles(tree: Tree, projectConfig: ProjectConfiguration, options: CypressComponentConfigurationSchema, found: FoundTarget): Promise<void>;
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addFiles = addFiles;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const versions_1 = require("nx/src/utils/versions");
6
- const component_test_1 = require("../../component-test/component-test");
7
6
  const ct_utils_1 = require("../../../utils/ct-utils");
7
+ const component_test_1 = require("../../component-test/component-test");
8
8
  async function addFiles(tree, projectConfig, options, found) {
9
- // must dyanmicaly import to prevent packages not using cypress from erroring out
9
+ // must dynamicaly import to prevent packages not using cypress from erroring out
10
10
  // when importing react
11
- const { addMountDefinition, addDefaultCTConfig } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/config'));
11
+ const { addMountDefinition } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/config'));
12
+ const { getInstalledCypressMajorVersion } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/versions'));
13
+ const installedCypressMajorVersion = getInstalledCypressMajorVersion(tree);
12
14
  // Specifically undefined to allow Remix workaround of passing an empty string
13
15
  const actualBundler = await (0, ct_utils_1.getActualBundler)(tree, options, found);
14
16
  if (options.bundler && options.bundler !== actualBundler) {
@@ -18,7 +20,8 @@ async function addFiles(tree, projectConfig, options, found) {
18
20
  const bundlerToUse = options.bundler ?? actualBundler;
19
21
  const commandFile = (0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'support', 'component.ts');
20
22
  const updatedCommandFile = await addMountDefinition(tree.read(commandFile, 'utf-8'));
21
- tree.write(commandFile, `import { mount } from 'cypress/react18';\n${updatedCommandFile}`);
23
+ const moduleSpecifier = installedCypressMajorVersion >= 14 ? 'cypress/react' : 'cypress/react18';
24
+ tree.write(commandFile, `import { mount } from '${moduleSpecifier}';\n${updatedCommandFile}`);
22
25
  if (options.bundler === 'webpack' ||
23
26
  (!options.bundler && actualBundler === 'webpack')) {
24
27
  (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@nx/webpack': versions_1.nxVersion });
@@ -1,16 +1,40 @@
1
- const { composePlugins, withNx, withReact } = require('@nx/rspack');
2
- const { withModuleFederation } = require('@nx/module-federation/rspack');
1
+ const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
2
+ const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
3
+ const { NxModuleFederationPlugin, NxModuleFederationDevServerPlugin } = require('@nx/module-federation/rspack');
4
+ const { join } = require('path');
3
5
 
4
- const baseConfig = require('./module-federation.config');
6
+ const config = require('./module-federation.config');
5
7
 
6
- const config = {
7
- ...baseConfig,
8
+ module.exports = {
9
+ output: {
10
+ path: join(__dirname, '<%= rspackPluginOptions.outputPath %>'),
11
+ publicPath: 'auto'
12
+ },
13
+ devServer: {
14
+ port: <%= devServerPort %>,
15
+ historyApiFallback: {
16
+ index: '/index.html',
17
+ disableDotRule: true,
18
+ htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
19
+ },
20
+ },
21
+ plugins: [
22
+ new NxAppRspackPlugin({
23
+ tsConfig: '<%= rspackPluginOptions.tsConfig %>',
24
+ main: '<%= rspackPluginOptions.main %>',
25
+ index: '<%= rspackPluginOptions.index %>',
26
+ baseHref: '<%= rspackPluginOptions.baseHref %>',
27
+ assets: <%- JSON.stringify(rspackPluginOptions.assets) %>,
28
+ styles: <%- JSON.stringify(rspackPluginOptions.styles) %>,
29
+ outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
30
+ optimization: process.env['NODE_ENV'] === 'production',
31
+ }),
32
+ new NxReactRspackPlugin({
33
+ // Uncomment this line if you don't want to use SVGR
34
+ // See: https://react-svgr.com/
35
+ // svgr: false
36
+ }),
37
+ new NxModuleFederationPlugin({ config }, { dts: false }),
38
+ new NxModuleFederationDevServerPlugin({ config }),
39
+ ],
8
40
  };
9
-
10
- // Nx plugins for rspack to build config object from Nx options and context.
11
- /**
12
- * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation
13
- * The DTS Plugin can be enabled by setting dts: true
14
- * Learn more about the DTS Plugin here: https://module-federation.io/configure/dts.html
15
- */
16
- module.exports = composePlugins(withNx(), withReact(), withModuleFederation(config, { dts: false }));
@@ -1,38 +1,66 @@
1
- const { composePlugins, withNx, withReact } = require('@nx/rspack');
2
- const { withModuleFederation } = require('@nx/module-federation/rspack');
1
+ const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
2
+ const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
3
+ const { NxModuleFederationPlugin, NxModuleFederationDevServerPlugin } = require('@nx/module-federation/rspack');
4
+ const { join } = require('path');
3
5
 
4
6
  const baseConfig = require('./module-federation.config');
5
7
 
6
8
  const prodConfig = {
7
- ...baseConfig,
8
- /*
9
- * Remote overrides for production.
10
- * Each entry is a pair of a unique name and the URL where it is deployed.
11
- *
12
- * e.g.
13
- * remotes: [
14
- * ['app1', 'http://app1.example.com'],
15
- * ['app2', 'http://app2.example.com'],
16
- * ]
17
- *
18
- * You can also use a full path to the remoteEntry.js file if desired.
19
- *
20
- * remotes: [
21
- * ['app1', 'http://example.com/path/to/app1/remoteEntry.js'],
22
- * ['app2', 'http://example.com/path/to/app2/remoteEntry.js'],
23
- * ]
24
- */
25
- remotes: [
26
- <%_ remotes.forEach(function(r) { _%>
27
- ['<%= r.fileName %>', 'http://localhost:<%= r.port %>/'],
28
- <%_ }); _%>
29
- ],
9
+ ...baseConfig,
10
+ /*
11
+ * Remote overrides for production.
12
+ * Each entry is a pair of a unique name and the URL where it is deployed.
13
+ *
14
+ * e.g.
15
+ * remotes: [
16
+ * ['app1', 'http://app1.example.com'],
17
+ * ['app2', 'http://app2.example.com'],
18
+ * ]
19
+ *
20
+ * You can also use a full path to the remoteEntry.js file if desired.
21
+ *
22
+ * remotes: [
23
+ * ['app1', 'http://example.com/path/to/app1/remoteEntry.js'],
24
+ * ['app2', 'http://example.com/path/to/app2/remoteEntry.js'],
25
+ * ]
26
+ */
27
+ remotes: [
28
+ <%_ remotes.forEach(function(r) { _%>
29
+ ['<%= r.fileName %>', 'http://localhost:<%= r.port %>/'],
30
+ <%_ }); _%>
31
+ ],
30
32
  };
31
33
 
32
- // Nx plugins for rspack to build config object from Nx options and context.
33
- /**
34
- * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation
35
- * The DTS Plugin can be enabled by setting dts: true
36
- * Learn more about the DTS Plugin here: https://module-federation.io/configure/dts.html
37
- */
38
- module.exports = composePlugins(withNx(), withReact(), withModuleFederation(prodConfig, { dts: false }));
34
+ module.exports = {
35
+ output: {
36
+ path: join(__dirname, '<%= rspackPluginOptions.outputPath %>'),
37
+ publicPath: 'auto'
38
+ },
39
+ devServer: {
40
+ port: <%= devServerPort %>,
41
+ historyApiFallback: {
42
+ index: '/index.html',
43
+ disableDotRule: true,
44
+ htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
45
+ },
46
+ },
47
+ plugins: [
48
+ new NxAppRspackPlugin({
49
+ tsConfig: '<%= rspackPluginOptions.tsConfig %>',
50
+ main: '<%= rspackPluginOptions.main %>',
51
+ index: '<%= rspackPluginOptions.index %>',
52
+ baseHref: '<%= rspackPluginOptions.baseHref %>',
53
+ assets: <%- JSON.stringify(rspackPluginOptions.assets) %>,
54
+ styles: <%- JSON.stringify(rspackPluginOptions.styles) %>,
55
+ outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
56
+ optimization: process.env['NODE_ENV'] === 'production',
57
+ }),
58
+ new NxReactRspackPlugin({
59
+ // Uncomment this line if you don't want to use SVGR
60
+ // See: https://react-svgr.com/
61
+ // svgr: false
62
+ }),
63
+ new NxModuleFederationPlugin({ config: prodConfig }, { dts: false }),
64
+ new NxModuleFederationDevServerPlugin({ config: prodConfig }),
65
+ ],
66
+ };
@@ -13,6 +13,12 @@ const moduleFederationConfig = {
13
13
  }
14
14
  _%>
15
15
  ],
16
+ shared: (libraryName, libraryConfig) => {
17
+ return {
18
+ ...libraryConfig,
19
+ eager: true
20
+ }
21
+ },
16
22
  };
17
23
 
18
24
  /**
@@ -0,0 +1,66 @@
1
+ const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
2
+ const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
3
+ const { NxModuleFederationPlugin, NxModuleFederationSSRDevServerPlugin } = require('@nx/module-federation/rspack');
4
+ const { join } = require('path');
5
+
6
+ const browserMfConfig = require('./module-federation.config');
7
+ const serverMfConfig = require('./module-federation.server.config');
8
+
9
+ const browserRspackConfig = {
10
+ name: 'browser',
11
+ output: {
12
+ path: join(__dirname, '<%= rspackPluginOptions.outputPath %>', 'browser'),
13
+ publicPath: 'auto'
14
+ },
15
+ devServer: {
16
+ port: <%= devServerPort %>,
17
+ historyApiFallback: {
18
+ index: '/index.html',
19
+ disableDotRule: true,
20
+ htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
21
+ },
22
+ devMiddleware: {
23
+ writeToDisk: (file: string) => !file.includes('.hot-update.'),
24
+ },
25
+ },
26
+ plugins: [
27
+ new NxAppRspackPlugin({
28
+ tsConfig: '<%= rspackPluginOptions.tsConfig %>',
29
+ main: '<%= rspackPluginOptions.main %>',
30
+ index: '<%= rspackPluginOptions.index %>',
31
+ baseHref: '<%= rspackPluginOptions.baseHref %>',
32
+ assets: <%- JSON.stringify(rspackPluginOptions.assets) %>,
33
+ styles: <%- JSON.stringify(rspackPluginOptions.styles) %>,
34
+ outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
35
+ optimization: process.env['NODE_ENV'] === 'production',
36
+ }),
37
+ new NxReactRspackPlugin({
38
+ // Uncomment this line if you don't want to use SVGR
39
+ // See: https://react-svgr.com/
40
+ // svgr: false
41
+ }),
42
+ new NxModuleFederationPlugin({ config: browserMfConfig }, { dts: false }),
43
+ ],
44
+ };
45
+
46
+ const serverRspackConfig = {
47
+ name: 'server',
48
+ target: 'async-node',
49
+ output: {
50
+ path: join(__dirname, '<%= rspackPluginOptions.outputPath %>', 'server'),
51
+ filename: 'server.js'
52
+ },
53
+ plugins: [
54
+ new NxAppRspackPlugin({
55
+ outputPath: join(__dirname, '<%= rspackPluginOptions.outputPath %>', 'server'),
56
+ outputFileName: 'server.js',
57
+ tsConfig: '<%= rspackPluginOptions.tsConfig %>',
58
+ main: '<%= rspackPluginOptions.mainServer %>',
59
+ baseHref: '<%= rspackPluginOptions.baseHref %>',
60
+ }),
61
+ new NxModuleFederationPlugin({ config: serverMfConfig, isServer: true }, { dts: false }),
62
+ new NxModuleFederationSSRDevServerPlugin({ config: serverMfConfig }),
63
+ ],
64
+ };
65
+
66
+ module.exports = [browserRspackConfig, serverRspackConfig];
@@ -7,7 +7,7 @@ import { handleRequest } from './src/main.server';
7
7
  const port = process.env['PORT'] || <%= port %>;
8
8
  const app = express();
9
9
 
10
- const browserDist = path.join(process.cwd(), '<%= browserBuildOutputPath %>');
10
+ const browserDist = path.join(process.cwd(), '<%= rspackPluginOptions.outputPath %>', 'browser');
11
11
  const indexPath = path.join(browserDist, 'index.html');
12
12
 
13
13
  app.use(cors());