@nx/rspack 21.0.0-beta.0 → 21.0.0-beta.10

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 (48) hide show
  1. package/generators.json +1 -0
  2. package/migrations.json +13 -34
  3. package/package.json +12 -10
  4. package/src/executors/dev-server/lib/get-dev-server-config.js +1 -2
  5. package/src/executors/dev-server/schema.json +1 -0
  6. package/src/executors/module-federation-dev-server/schema.json +1 -0
  7. package/src/executors/module-federation-ssr-dev-server/schema.json +1 -0
  8. package/src/executors/module-federation-static-server/schema.json +1 -0
  9. package/src/executors/rspack/lib/normalize-options.js +1 -0
  10. package/src/executors/rspack/schema.d.ts +6 -1
  11. package/src/executors/rspack/schema.json +14 -0
  12. package/src/executors/ssr-dev-server/schema.json +1 -0
  13. package/src/generators/application/application.js +0 -3
  14. package/src/generators/application/lib/normalize-options.js +7 -7
  15. package/src/generators/configuration/configuration.js +0 -3
  16. package/src/generators/convert-to-inferred/schema.json +4 -4
  17. package/src/generators/convert-webpack/convert-webpack.js +23 -0
  18. package/src/generators/convert-webpack/lib/transform-cjs.js +81 -0
  19. package/src/generators/convert-webpack/lib/transform-esm.js +81 -0
  20. package/src/generators/init/init.js +4 -1
  21. package/src/index.d.ts +1 -0
  22. package/src/index.js +1 -0
  23. package/src/migrations/update-20-2-0/migrate-with-mf-import-to-new-package.md +30 -0
  24. package/src/migrations/update-20-3-0/ensure-nx-module-federation-package.md +28 -0
  25. package/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.js +10 -0
  26. package/src/plugins/plugin.js +34 -9
  27. package/src/plugins/utils/apply-base-config.js +50 -13
  28. package/src/plugins/utils/apply-web-config.js +42 -11
  29. package/src/plugins/utils/is-lib-buildable.d.ts +7 -0
  30. package/src/plugins/utils/is-lib-buildable.js +48 -0
  31. package/src/plugins/utils/loaders/stylesheet-loaders.js +1 -1
  32. package/src/plugins/utils/models.d.ts +17 -2
  33. package/src/plugins/utils/plugins/normalize-options.js +3 -0
  34. package/src/plugins/write-index-html-plugin.d.ts +22 -0
  35. package/src/plugins/write-index-html-plugin.js +250 -0
  36. package/src/utils/e2e-web-server-info-utils.d.ts +2 -0
  37. package/src/utils/e2e-web-server-info-utils.js +25 -0
  38. package/src/utils/versions.d.ts +3 -3
  39. package/src/utils/versions.js +4 -4
  40. package/src/utils/webpack/interpolate-env-variables-to-index.d.ts +1 -0
  41. package/src/utils/webpack/interpolate-env-variables-to-index.js +29 -0
  42. package/src/utils/webpack/normalize-entry.d.ts +2 -0
  43. package/src/utils/webpack/normalize-entry.js +27 -0
  44. package/src/utils/webpack/package-chunk-sort.d.ts +5 -0
  45. package/src/utils/webpack/package-chunk-sort.js +30 -0
  46. package/src/utils/with-nx.js +1 -0
  47. package/src/utils/with-web.d.ts +7 -0
  48. package/src/utils/with-web.js +1 -0
package/generators.json CHANGED
@@ -28,6 +28,7 @@
28
28
  "description": "React application generator."
29
29
  },
30
30
  "convert-webpack": {
31
+ "alias": "convert-to-rspack",
31
32
  "factory": "./src/generators/convert-webpack/convert-webpack",
32
33
  "schema": "./src/generators/convert-webpack/schema.json",
33
34
  "description": "Convert a webpack application to use rspack."
package/migrations.json CHANGED
@@ -14,40 +14,6 @@
14
14
  }
15
15
  },
16
16
  "packageJsonUpdates": {
17
- "18.1.0": {
18
- "version": "18.1.0-beta.0",
19
- "packages": {
20
- "@rspack/core": {
21
- "version": "~0.5.6",
22
- "alwaysAddToPackageJson": false
23
- },
24
- "@rspack/dev-server": {
25
- "version": "~0.5.6",
26
- "alwaysAddToPackageJson": false
27
- },
28
- "@rspack/plugin-minify": {
29
- "version": "~0.5.6",
30
- "alwaysAddToPackageJson": false
31
- }
32
- }
33
- },
34
- "18.1.3": {
35
- "version": "18.1.3",
36
- "packages": {
37
- "@rspack/core": {
38
- "version": "^0.6.1",
39
- "alwaysAddToPackageJson": false
40
- },
41
- "@rspack/dev-server": {
42
- "version": "^0.6.1",
43
- "alwaysAddToPackageJson": false
44
- },
45
- "@rspack/plugin-minify": {
46
- "version": "^0.6.1",
47
- "alwaysAddToPackageJson": false
48
- }
49
- }
50
- },
51
17
  "19.3.0": {
52
18
  "version": "19.3.0-beta.0",
53
19
  "packages": {
@@ -94,6 +60,19 @@
94
60
  "alwaysAddToPackageJson": false
95
61
  }
96
62
  }
63
+ },
64
+ "20.5.0": {
65
+ "version": "20.5.0-beta.4",
66
+ "packages": {
67
+ "sass-loader": {
68
+ "version": "^16.0.4",
69
+ "alwaysAddToPackageJson": false
70
+ },
71
+ "@rspack/core": {
72
+ "version": "^1.2.2",
73
+ "alwaysAddToPackageJson": false
74
+ }
75
+ }
97
76
  }
98
77
  },
99
78
  "version": "0.1"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nx/rspack",
3
3
  "description": "The Nx Plugin for Rspack contains executors and generators that support building applications using Rspack.",
4
- "version": "21.0.0-beta.0",
4
+ "version": "21.0.0-beta.10",
5
5
  "type": "commonjs",
6
6
  "repository": {
7
7
  "type": "git",
@@ -24,10 +24,10 @@
24
24
  "generators": "./generators.json",
25
25
  "executors": "./executors.json",
26
26
  "dependencies": {
27
- "@nx/js": "21.0.0-beta.0",
28
- "@nx/devkit": "21.0.0-beta.0",
29
- "@nx/web": "21.0.0-beta.0",
30
- "@nx/module-federation": "21.0.0-beta.0",
27
+ "@nx/js": "21.0.0-beta.10",
28
+ "@nx/devkit": "21.0.0-beta.10",
29
+ "@nx/web": "21.0.0-beta.10",
30
+ "@nx/module-federation": "21.0.0-beta.10",
31
31
  "@phenomnomnominal/tsquery": "~5.0.1",
32
32
  "@rspack/core": "^1.1.5",
33
33
  "@rspack/dev-server": "^1.0.9",
@@ -37,13 +37,15 @@
37
37
  "css-loader": "^6.4.0",
38
38
  "enquirer": "~2.3.6",
39
39
  "express": "^4.21.2",
40
- "fork-ts-checker-webpack-plugin": "7.2.13",
40
+ "ts-checker-rspack-plugin": "^1.1.1",
41
41
  "http-proxy-middleware": "^3.0.3",
42
42
  "less-loader": "11.1.0",
43
43
  "license-webpack-plugin": "^4.0.2",
44
44
  "loader-utils": "^2.0.3",
45
- "sass": "^1.42.1",
46
- "sass-loader": "^12.2.0",
45
+ "parse5": "4.0.0",
46
+ "sass": "^1.85.0",
47
+ "sass-embedded": "^1.83.4",
48
+ "sass-loader": "^16.0.4",
47
49
  "source-map-loader": "^5.0.0",
48
50
  "style-loader": "^3.3.0",
49
51
  "picocolors": "^1.1.0",
@@ -55,8 +57,8 @@
55
57
  "webpack-node-externals": "^3.0.0"
56
58
  },
57
59
  "peerDependencies": {
58
- "@module-federation/enhanced": "^0.8.8",
59
- "@module-federation/node": "^2.6.21"
60
+ "@module-federation/enhanced": "^0.9.0",
61
+ "@module-federation/node": "^2.6.26"
60
62
  },
61
63
  "nx-migrations": {
62
64
  "migrations": "./migrations.json"
@@ -31,8 +31,7 @@ function getDevServerOptions(root, serveOptions, buildOptions) {
31
31
  htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
32
32
  },
33
33
  onListening(server) {
34
- const isHttps = server.options.https ||
35
- server.options.server?.type === 'https';
34
+ const isHttps = server.options.server?.type === 'https';
36
35
  devkit_1.logger.info(`NX Web Development Server is listening at ${isHttps ? 'https' : 'http'}://${server.options.host}:${server.options.port}${(0, serve_path_1.buildServePath)(buildOptions)}`);
37
36
  },
38
37
  open: false,
@@ -3,6 +3,7 @@
3
3
  "version": 2,
4
4
  "title": "Rspack dev-server executor",
5
5
  "description": "Run @rspack/dev-server to serve a project.",
6
+ "continuous": true,
6
7
  "type": "object",
7
8
  "properties": {
8
9
  "buildTarget": {
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "version": 2,
3
+ "continuous": true,
3
4
  "outputCapture": "direct-nodejs",
4
5
  "title": "Rspack Module Federation Dev Server",
5
6
  "description": "Serve a module federation application.",
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "version": 2,
3
+ "continuous": true,
3
4
  "outputCapture": "direct-nodejs",
4
5
  "title": "Module Federation SSR Dev Server",
5
6
  "description": "Serve a SSR Consumer (host) application along with its known Producers (remotes).",
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "version": 2,
3
+ "continuous": true,
3
4
  "outputCapture": "direct-nodejs",
4
5
  "title": "Module Federation Static Dev Server",
5
6
  "description": "Serve a Consumer (host) application statically along with it's Producers (remotes).",
@@ -22,6 +22,7 @@ function normalizeOptions(options, root, projectRoot, sourceRoot) {
22
22
  styles: options.optimization,
23
23
  }
24
24
  : options.optimization,
25
+ sassImplementation: options.sassImplementation ?? 'sass',
25
26
  };
26
27
  if (options.assets) {
27
28
  normalizedOptions.assets = (0, normalize_options_1.normalizeAssets)(options.assets, root, sourceRoot, projectRoot, false // executor assets are relative to workspace root for consistency
@@ -35,7 +35,12 @@ export interface RspackExecutorSchema {
35
35
  sourceMap?: boolean | DevTool;
36
36
  standardRspackConfigFunction?: boolean;
37
37
  statsJson?: boolean;
38
- stylePreprocessorOptions?: any;
38
+ stylePreprocessorOptions?: {
39
+ includePaths?: string[];
40
+ sassOptions?: Record<string, any>;
41
+ lessOptions?: Record<string, any>;
42
+ };
43
+ sassImplementation?: 'sass' | 'sass-embedded';
39
44
  styles?: Array<ExtraEntryPointClass | string>;
40
45
  target?: 'web' | 'node';
41
46
  transformers?: TransformerEntry[];
@@ -245,10 +245,24 @@
245
245
  "items": {
246
246
  "type": "string"
247
247
  }
248
+ },
249
+ "sassOptions": {
250
+ "description": "Options to pass to sass-loader.",
251
+ "type": "object"
252
+ },
253
+ "lessOptions": {
254
+ "description": "Options to pass to less-loader.",
255
+ "type": "object"
248
256
  }
249
257
  },
250
258
  "additionalProperties": false
251
259
  },
260
+ "sassImplementation": {
261
+ "type": "string",
262
+ "description": "The implementation of the SASS compiler to use. Can be either `sass` or `sass-embedded`. Defaults to `sass-embedded`.",
263
+ "enum": ["sass", "sass-embedded"],
264
+ "default": "sass"
265
+ },
252
266
  "styles": {
253
267
  "type": "array",
254
268
  "description": "External Styles which will be included with the application",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "continuous": true,
2
3
  "outputCapture": "direct-nodejs",
3
4
  "title": "Rspack SSR Dev Server",
4
5
  "description": "Serve a SSR application using rspack.",
@@ -11,9 +11,6 @@ async function default_1(tree, _options) {
11
11
  const tasks = [];
12
12
  const initTask = await (0, init_1.default)(tree, {
13
13
  ..._options,
14
- // TODO: Crystalize the default rspack.config.js file.
15
- // The default setup isn't crystalized so don't add plugin.
16
- addPlugin: false,
17
14
  });
18
15
  tasks.push(initTask);
19
16
  const options = await (0, normalize_options_1.normalizeOptions)(tree, _options);
@@ -1,24 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeOptions = normalizeOptions;
4
- const devkit_1 = require("@nx/devkit");
5
4
  const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
5
+ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
6
6
  async function normalizeOptions(host, options) {
7
- await (0, project_name_and_root_utils_1.ensureProjectName)(host, options, 'application');
8
- const { projectName: appProjectName, projectRoot: appProjectRoot } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
7
+ await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'application');
8
+ const { projectName, projectRoot: appProjectRoot, importPath, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
9
9
  ...options,
10
10
  projectType: 'application',
11
11
  });
12
12
  // --monorepo takes precedence over --rootProject
13
13
  // This won't be needed once we add --bundler=rspack to the @nx/react:app preset
14
14
  const rootProject = !options.monorepo && options.rootProject;
15
- const e2eProjectName = options.rootProject
16
- ? 'e2e'
17
- : `${(0, devkit_1.names)(appProjectName).fileName}-e2e`;
15
+ const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host);
16
+ const appProjectName = !isTsSolutionSetup || options.name ? projectName : importPath;
17
+ const e2eProjectName = options.rootProject ? 'e2e' : `${projectName}-e2e`;
18
18
  const normalized = {
19
19
  ...options,
20
20
  rootProject,
21
- name: (0, devkit_1.names)(options.name).fileName,
21
+ name: appProjectName,
22
22
  projectName: appProjectName,
23
23
  appProjectRoot,
24
24
  e2eProjectName,
@@ -10,9 +10,6 @@ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-set
10
10
  async function configurationGenerator(tree, options) {
11
11
  const task = await (0, init_1.default)(tree, {
12
12
  ...options,
13
- // TODO: Crystalize the default rspack.config.js file.
14
- // The default setup isn't crystalized so don't add plugin.
15
- addPlugin: false,
16
13
  });
17
14
  const { targets, root, projectType } = (0, devkit_1.readProjectConfiguration)(tree, options.project);
18
15
  const { target, framework } = (0, generator_utils_1.determineFrameworkAndTarget)(tree, options, root, targets);
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/schema",
3
- "$id": "NxWebpackConvertToInferred",
4
- "description": "Convert existing Webpack project(s) using `@nx/webpack:wepack` executor to use `@nx/webpack/plugin`.",
5
- "title": "Convert a Webpack project from executor to plugin",
3
+ "$id": "NxRspackConvertToInferred",
4
+ "description": "Convert existing Rspack project(s) using `@nx/rspack:rspack` executor to use `@nx/rspack/plugin`.",
5
+ "title": "Convert a Rspack project from executor to plugin",
6
6
  "type": "object",
7
7
  "properties": {
8
8
  "project": {
9
9
  "type": "string",
10
- "description": "The project to convert from using the `@nx/webpack:webpack` executor to use `@nx/webpack/plugin`. If not provided, all projects using the `@nx/webpack:webpack` executor will be converted.",
10
+ "description": "The project to convert from using the `@nx/rspack:rspack` executor to use `@nx/rspack/plugin`. If not provided, all projects using the `@nx/rspack:rspack` executor will be converted.",
11
11
  "x-priority": "important"
12
12
  },
13
13
  "skipFormat": {
@@ -57,6 +57,29 @@ async function default_1(tree, options) {
57
57
  transformConfigFile(tree, rspackConfigPath);
58
58
  }
59
59
  (0, devkit_1.updateProjectConfiguration)(tree, options.project, project);
60
+ const nxJson = (0, devkit_1.readNxJson)(tree);
61
+ if (nxJson.plugins !== undefined && nxJson.plugins.length > 0) {
62
+ const nonRspackPlugins = nxJson.plugins.filter((plugin) => (typeof plugin !== 'string' && plugin.plugin !== '@nx/rspack/plugin') ||
63
+ (typeof plugin === 'string' && plugin !== '@nx/rspack/plugin'));
64
+ let rspackPlugins = nxJson.plugins.filter((plugin) => (typeof plugin !== 'string' && plugin.plugin === '@nx/rspack/plugin') ||
65
+ (typeof plugin === 'string' && plugin === '@nx/rspack/plugin'));
66
+ if (rspackPlugins.length === 0) {
67
+ rspackPlugins = rspackPlugins.map((plugin) => {
68
+ if (typeof plugin === 'string') {
69
+ return {
70
+ plugin: plugin,
71
+ exclude: [`${project.root}/*`],
72
+ };
73
+ }
74
+ return {
75
+ ...plugin,
76
+ exclude: [...(plugin.exclude ?? []), `${project.root}/*`],
77
+ };
78
+ });
79
+ nxJson.plugins = [...nonRspackPlugins, ...rspackPlugins];
80
+ (0, devkit_1.updateNxJson)(tree, nxJson);
81
+ }
82
+ }
60
83
  const installTask = (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
61
84
  '@rspack/core': versions_1.rspackCoreVersion,
62
85
  '@rspack/dev-server': versions_1.rspackDevServerVersion,
@@ -12,6 +12,87 @@ function transformCjsConfigFile(tree, configPath) {
12
12
  transformWithModuleFederation(tree, configPath, scope);
13
13
  transformWithModuleFederationSSR(tree, configPath, scope);
14
14
  });
15
+ // Add useLegacyHtmlPlugin: true to withWeb() calls
16
+ transformWithWebCalls(tree, configPath);
17
+ }
18
+ function transformWithWebCalls(tree, configPath) {
19
+ const configContents = tree.read(configPath, 'utf-8');
20
+ const ast = tsquery_1.tsquery.ast(configContents);
21
+ // Find withWeb() calls
22
+ const withWebCallNodes = (0, tsquery_1.tsquery)(ast, 'CallExpression > Identifier[name=withWeb]');
23
+ // If there are withWeb calls, update them
24
+ if (withWebCallNodes.length > 0) {
25
+ let newContents = configContents;
26
+ for (const node of withWebCallNodes) {
27
+ const callExpr = node.parent;
28
+ if (!callExpr)
29
+ continue;
30
+ const startPos = callExpr.getStart();
31
+ const endPos = callExpr.getEnd();
32
+ const callText = configContents.substring(startPos, endPos);
33
+ // Skip if useLegacyHtmlPlugin is already present
34
+ if (callText.includes('useLegacyHtmlPlugin')) {
35
+ continue;
36
+ }
37
+ // If it's already withWeb({ ... }), add useLegacyHtmlPlugin: true to the options
38
+ if (callText.includes('{') && callText.includes('}')) {
39
+ const newCallText = callText.replace(/\{\s*/, '{ useLegacyHtmlPlugin: true,\n ');
40
+ newContents =
41
+ newContents.substring(0, startPos) +
42
+ newCallText +
43
+ newContents.substring(endPos);
44
+ }
45
+ else {
46
+ // If it's just withWeb(), replace with withWeb({ useLegacyHtmlPlugin: true })
47
+ const newCallText = 'withWeb({ useLegacyHtmlPlugin: true })';
48
+ newContents =
49
+ newContents.substring(0, startPos) +
50
+ newCallText +
51
+ newContents.substring(endPos);
52
+ }
53
+ }
54
+ if (newContents !== configContents) {
55
+ tree.write(configPath, newContents);
56
+ }
57
+ return;
58
+ }
59
+ // If no withWeb calls, check for withReact calls
60
+ const withReactCallNodes = (0, tsquery_1.tsquery)(ast, 'CallExpression > Identifier[name=withReact]');
61
+ if (withReactCallNodes.length === 0) {
62
+ return;
63
+ }
64
+ let newContents = configContents;
65
+ for (const node of withReactCallNodes) {
66
+ const callExpr = node.parent;
67
+ if (!callExpr)
68
+ continue;
69
+ const startPos = callExpr.getStart();
70
+ const endPos = callExpr.getEnd();
71
+ const callText = configContents.substring(startPos, endPos);
72
+ // Skip if useLegacyHtmlPlugin is already present
73
+ if (callText.includes('useLegacyHtmlPlugin')) {
74
+ continue;
75
+ }
76
+ // If it's already withReact({ ... }), add useLegacyHtmlPlugin: true to the options
77
+ if (callText.includes('{') && callText.includes('}')) {
78
+ const newCallText = callText.replace(/\{\s*/, '{ useLegacyHtmlPlugin: true,\n ');
79
+ newContents =
80
+ newContents.substring(0, startPos) +
81
+ newCallText +
82
+ newContents.substring(endPos);
83
+ }
84
+ else {
85
+ // If it's just withReact(), replace with withReact({ useLegacyHtmlPlugin: true })
86
+ const newCallText = 'withReact({ useLegacyHtmlPlugin: true })';
87
+ newContents =
88
+ newContents.substring(0, startPos) +
89
+ newCallText +
90
+ newContents.substring(endPos);
91
+ }
92
+ }
93
+ if (newContents !== configContents) {
94
+ tree.write(configPath, newContents);
95
+ }
15
96
  }
16
97
  function transformComposePlugins(tree, configPath, scope) {
17
98
  const configContents = tree.read(configPath, 'utf-8');
@@ -12,6 +12,87 @@ function transformEsmConfigFile(tree, configPath) {
12
12
  transformWithModuleFederation(tree, configPath, scope);
13
13
  transformWithModuleFederationSSR(tree, configPath, scope);
14
14
  });
15
+ // Add useLegacyHtmlPlugin: true to withWeb() calls
16
+ transformWithWebCalls(tree, configPath);
17
+ }
18
+ function transformWithWebCalls(tree, configPath) {
19
+ const configContents = tree.read(configPath, 'utf-8');
20
+ const ast = tsquery_1.tsquery.ast(configContents);
21
+ // Find withWeb() calls
22
+ const withWebCallNodes = (0, tsquery_1.tsquery)(ast, 'CallExpression > Identifier[name=withWeb]');
23
+ // If there are withWeb calls, update them
24
+ if (withWebCallNodes.length > 0) {
25
+ let newContents = configContents;
26
+ for (const node of withWebCallNodes) {
27
+ const callExpr = node.parent;
28
+ if (!callExpr)
29
+ continue;
30
+ const startPos = callExpr.getStart();
31
+ const endPos = callExpr.getEnd();
32
+ const callText = configContents.substring(startPos, endPos);
33
+ // Skip if useLegacyHtmlPlugin is already present
34
+ if (callText.includes('useLegacyHtmlPlugin')) {
35
+ continue;
36
+ }
37
+ // If it's already withWeb({ ... }), add useLegacyHtmlPlugin: true to the options
38
+ if (callText.includes('{') && callText.includes('}')) {
39
+ const newCallText = callText.replace(/\{\s*/, '{ useLegacyHtmlPlugin: true,\n ');
40
+ newContents =
41
+ newContents.substring(0, startPos) +
42
+ newCallText +
43
+ newContents.substring(endPos);
44
+ }
45
+ else {
46
+ // If it's just withWeb(), replace with withWeb({ useLegacyHtmlPlugin: true })
47
+ const newCallText = 'withWeb({ useLegacyHtmlPlugin: true })';
48
+ newContents =
49
+ newContents.substring(0, startPos) +
50
+ newCallText +
51
+ newContents.substring(endPos);
52
+ }
53
+ }
54
+ if (newContents !== configContents) {
55
+ tree.write(configPath, newContents);
56
+ }
57
+ return;
58
+ }
59
+ // If no withWeb calls, check for withReact calls
60
+ const withReactCallNodes = (0, tsquery_1.tsquery)(ast, 'CallExpression > Identifier[name=withReact]');
61
+ if (withReactCallNodes.length === 0) {
62
+ return;
63
+ }
64
+ let newContents = configContents;
65
+ for (const node of withReactCallNodes) {
66
+ const callExpr = node.parent;
67
+ if (!callExpr)
68
+ continue;
69
+ const startPos = callExpr.getStart();
70
+ const endPos = callExpr.getEnd();
71
+ const callText = configContents.substring(startPos, endPos);
72
+ // Skip if useLegacyHtmlPlugin is already present
73
+ if (callText.includes('useLegacyHtmlPlugin')) {
74
+ continue;
75
+ }
76
+ // If it's already withReact({ ... }), add useLegacyHtmlPlugin: true to the options
77
+ if (callText.includes('{') && callText.includes('}')) {
78
+ const newCallText = callText.replace(/\{\s*/, '{ useLegacyHtmlPlugin: true,\n ');
79
+ newContents =
80
+ newContents.substring(0, startPos) +
81
+ newCallText +
82
+ newContents.substring(endPos);
83
+ }
84
+ else {
85
+ // If it's just withReact(), replace with withReact({ useLegacyHtmlPlugin: true })
86
+ const newCallText = 'withReact({ useLegacyHtmlPlugin: true })';
87
+ newContents =
88
+ newContents.substring(0, startPos) +
89
+ newCallText +
90
+ newContents.substring(endPos);
91
+ }
92
+ }
93
+ if (newContents !== configContents) {
94
+ tree.write(configPath, newContents);
95
+ }
15
96
  }
16
97
  function transformComposePlugins(tree, configPath, scope) {
17
98
  const configContents = tree.read(configPath, 'utf-8');
@@ -57,7 +57,6 @@ async function rspackInitGenerator(tree, schema) {
57
57
  const devDependencies = {
58
58
  '@rspack/core': versions_1.rspackCoreVersion,
59
59
  '@rspack/cli': versions_1.rspackCoreVersion,
60
- '@rspack/plugin-minify': versions_1.rspackPluginMinifyVersion,
61
60
  '@rspack/plugin-react-refresh': versions_1.rspackPluginReactRefreshVersion,
62
61
  'react-refresh': versions_1.reactRefreshVersion,
63
62
  };
@@ -70,6 +69,10 @@ async function rspackInitGenerator(tree, schema) {
70
69
  if (schema.style === 'less') {
71
70
  devDependencies['less-loader'] = versions_1.lessLoaderVersion;
72
71
  }
72
+ if (schema.style === 'scss') {
73
+ devDependencies['sass-loader'] = versions_1.sassLoaderVersion;
74
+ devDependencies['sass-embedded'] = versions_1.sassEmbeddedVersion;
75
+ }
73
76
  if (schema.framework !== 'none' || schema.devServer) {
74
77
  devDependencies['@rspack/dev-server'] = versions_1.rspackDevServerVersion;
75
78
  }
package/src/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export * from './utils/config';
4
4
  export * from './utils/with-nx';
5
5
  export * from './utils/with-react';
6
6
  export * from './utils/with-web';
7
+ export * from './utils/e2e-web-server-info-utils';
7
8
  export * from './plugins/use-legacy-nx-plugin/use-legacy-nx-plugin';
package/src/index.js CHANGED
@@ -7,4 +7,5 @@ tslib_1.__exportStar(require("./utils/config"), exports);
7
7
  tslib_1.__exportStar(require("./utils/with-nx"), exports);
8
8
  tslib_1.__exportStar(require("./utils/with-react"), exports);
9
9
  tslib_1.__exportStar(require("./utils/with-web"), exports);
10
+ tslib_1.__exportStar(require("./utils/e2e-web-server-info-utils"), exports);
10
11
  tslib_1.__exportStar(require("./plugins/use-legacy-nx-plugin/use-legacy-nx-plugin"), exports);
@@ -0,0 +1,30 @@
1
+ #### Migrate withModuleFederation Import to New Package
2
+
3
+ Update the withModuleFederation import to use @nx/module-federation/rspack.
4
+
5
+ #### Sample Code Changes
6
+
7
+ Update import paths for `withModuleFederation` and `withModuleFederationForSSR`.
8
+
9
+ {% tabs %}
10
+ {% tab label="Before" %}
11
+
12
+ ```ts {% fileName="apps/shell/rspack.config.ts" %}
13
+ import {
14
+ withModuleFederation,
15
+ withModuleFederationForSSR,
16
+ } from '@nx/rspack/module-federation';
17
+ ```
18
+
19
+ {% /tab %}
20
+ {% tab label="After" %}
21
+
22
+ ```ts {% fileName="apps/shell/rspack.config.ts" %}
23
+ import {
24
+ withModuleFederation,
25
+ withModuleFederationForSSR,
26
+ } from '@nx/module-federation/rspack';
27
+ ```
28
+
29
+ {% /tab %}
30
+ {% /tabs %}
@@ -0,0 +1,28 @@
1
+ #### Ensure the @nx/module-federation Package is Installed
2
+
3
+ If workspace includes Module Federation projects, ensure the new `@nx/module-federation` package is installed.
4
+
5
+ #### Sample Code Changes
6
+
7
+ {% tabs %}
8
+ {% tab label="Before" %}
9
+
10
+ ```json {% fileName="package.json" %}
11
+ {
12
+ "dependencies": {}
13
+ }
14
+ ```
15
+
16
+ {% /tab %}
17
+ {% tab label="After" %}
18
+
19
+ ```json {% fileName="package.json" %}
20
+ {
21
+ "dependencies": {
22
+ "@nx/module-federation": "20.3.0"
23
+ }
24
+ }
25
+ ```
26
+
27
+ {% /tab %}
28
+ {% /tabs %}
@@ -27,6 +27,16 @@ class NxAppRspackPlugin {
27
27
  if (typeof target === 'string') {
28
28
  this.options.target = target;
29
29
  }
30
+ if (compiler.options.entry &&
31
+ compiler.options.entry['main'] &&
32
+ typeof compiler.options.entry['main'] === 'object' &&
33
+ Object.keys(compiler.options.entry['main']).length === 0) {
34
+ compiler.options.entry = {};
35
+ }
36
+ // Prefer `clean` option from Rspack config over our own.
37
+ if (typeof compiler.options.output.clean !== 'undefined') {
38
+ this.options.deleteOutputPath = false;
39
+ }
30
40
  (0, apply_base_config_1.applyBaseConfig)(this.options, compiler.options, {
31
41
  useNormalizedEntry: true,
32
42
  });