@nx/rspack 21.0.0-beta.1 → 21.0.0-beta.3

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 (30) hide show
  1. package/generators.json +1 -0
  2. package/migrations.json +13 -0
  3. package/package.json +11 -10
  4. package/src/executors/dev-server/lib/get-dev-server-config.js +1 -2
  5. package/src/executors/rspack/lib/normalize-options.js +1 -0
  6. package/src/executors/rspack/schema.d.ts +6 -1
  7. package/src/executors/rspack/schema.json +14 -0
  8. package/src/generators/application/application.js +0 -3
  9. package/src/generators/application/lib/normalize-options.js +7 -7
  10. package/src/generators/configuration/configuration.js +0 -3
  11. package/src/generators/convert-webpack/convert-webpack.js +23 -0
  12. package/src/generators/init/init.js +4 -1
  13. package/src/index.d.ts +1 -0
  14. package/src/index.js +1 -0
  15. package/src/migrations/update-20-2-0/migrate-with-mf-import-to-new-package.md +30 -0
  16. package/src/migrations/update-20-3-0/ensure-nx-module-federation-package.md +28 -0
  17. package/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.js +10 -0
  18. package/src/plugins/plugin.js +34 -9
  19. package/src/plugins/utils/apply-base-config.js +50 -12
  20. package/src/plugins/utils/apply-web-config.js +20 -3
  21. package/src/plugins/utils/is-lib-buildable.d.ts +7 -0
  22. package/src/plugins/utils/is-lib-buildable.js +48 -0
  23. package/src/plugins/utils/loaders/stylesheet-loaders.js +1 -1
  24. package/src/plugins/utils/models.d.ts +11 -2
  25. package/src/plugins/utils/plugins/normalize-options.js +1 -0
  26. package/src/utils/e2e-web-server-info-utils.d.ts +2 -0
  27. package/src/utils/e2e-web-server-info-utils.js +25 -0
  28. package/src/utils/versions.d.ts +3 -3
  29. package/src/utils/versions.js +4 -4
  30. package/src/utils/with-web.d.ts +3 -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
@@ -94,6 +94,19 @@
94
94
  "alwaysAddToPackageJson": false
95
95
  }
96
96
  }
97
+ },
98
+ "20.5.0": {
99
+ "version": "20.5.0-beta.4",
100
+ "packages": {
101
+ "sass-loader": {
102
+ "version": "^16.0.4",
103
+ "alwaysAddToPackageJson": false
104
+ },
105
+ "@rspack/core": {
106
+ "version": "^1.2.2",
107
+ "alwaysAddToPackageJson": false
108
+ }
109
+ }
97
110
  }
98
111
  },
99
112
  "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.1",
4
+ "version": "21.0.0-beta.3",
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.1",
28
- "@nx/devkit": "21.0.0-beta.1",
29
- "@nx/web": "21.0.0-beta.1",
30
- "@nx/module-federation": "21.0.0-beta.1",
27
+ "@nx/js": "21.0.0-beta.3",
28
+ "@nx/devkit": "21.0.0-beta.3",
29
+ "@nx/web": "21.0.0-beta.3",
30
+ "@nx/module-federation": "21.0.0-beta.3",
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,14 @@
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
+ "sass": "^1.85.0",
46
+ "sass-embedded": "^1.83.4",
47
+ "sass-loader": "^16.0.4",
47
48
  "source-map-loader": "^5.0.0",
48
49
  "style-loader": "^3.3.0",
49
50
  "picocolors": "^1.1.0",
@@ -55,8 +56,8 @@
55
56
  "webpack-node-externals": "^3.0.0"
56
57
  },
57
58
  "peerDependencies": {
58
- "@module-federation/enhanced": "^0.8.8",
59
- "@module-federation/node": "^2.6.21"
59
+ "@module-federation/enhanced": "^0.9.0",
60
+ "@module-federation/node": "^2.6.26"
60
61
  },
61
62
  "nx-migrations": {
62
63
  "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,
@@ -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",
@@ -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);
@@ -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,
@@ -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
  });
@@ -14,7 +14,14 @@ const resolve_user_defined_rspack_config_1 = require("../utils/resolve-user-defi
14
14
  const util_1 = require("@nx/js/src/plugins/typescript/util");
15
15
  const pmc = (0, devkit_1.getPackageManagerCommand)();
16
16
  function readTargetsCache(cachePath) {
17
- return (0, fs_1.existsSync)(cachePath) ? (0, devkit_1.readJsonFile)(cachePath) : {};
17
+ try {
18
+ return process.env.NX_CACHE_PROJECT_GRAPH !== 'false'
19
+ ? (0, devkit_1.readJsonFile)(cachePath)
20
+ : {};
21
+ }
22
+ catch {
23
+ return {};
24
+ }
18
25
  }
19
26
  function writeTargetsToCache(cachePath, results) {
20
27
  (0, devkit_1.writeJsonFile)(cachePath, results);
@@ -52,16 +59,15 @@ async function createNodesInternal(configFilePath, options, context, targetsCach
52
59
  packageJson = (0, devkit_1.readJsonFile)((0, path_1.join)(context.workspaceRoot, projectRoot, 'package.json'));
53
60
  }
54
61
  const normalizedOptions = normalizeOptions(options);
55
- // We do not want to alter how the hash is calculated, so appending the config file path to the hash
56
- // to prevent vite/vitest files overwriting the target cache created by the other
62
+ const lockFileHash = (0, file_hasher_1.hashFile)((0, path_1.join)(context.workspaceRoot, (0, js_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot)))) ?? '';
57
63
  const nodeHash = (0, file_hasher_1.hashArray)([
58
- ...[
59
- (0, path_1.join)(context.workspaceRoot, configFilePath),
60
- (0, path_1.join)(context.workspaceRoot, (0, js_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot))),
61
- ].map(file_hasher_1.hashFile),
62
- (0, file_hasher_1.hashObject)(options),
64
+ (0, file_hasher_1.hashFile)((0, path_1.join)(context.workspaceRoot, configFilePath)),
65
+ lockFileHash,
66
+ (0, file_hasher_1.hashObject)({ ...options, isTsSolutionSetup }),
63
67
  (0, file_hasher_1.hashObject)(packageJson),
64
68
  ]);
69
+ // We do not want to alter how the hash is calculated, so appending the config file path to the hash
70
+ // to prevent vite/vitest files overwriting the target cache created by the other
65
71
  const hash = `${nodeHash}_${configFilePath}`;
66
72
  targetsCache[hash] ??= await createRspackTargets(configFilePath, projectRoot, normalizedOptions, context, isTsSolutionSetup);
67
73
  const { targets, metadata } = targetsCache[hash];
@@ -86,9 +92,23 @@ async function createRspackTargets(configFilePath, projectRoot, options, context
86
92
  }
87
93
  }
88
94
  const targets = {};
95
+ const env = {};
96
+ const isTsConfig = ['.ts', '.cts', '.mts'].includes((0, path_1.extname)(configFilePath));
97
+ if (isTsConfig) {
98
+ // https://rspack.dev/config/#using-ts-node
99
+ env['TS_NODE_COMPILER_OPTIONS'] = JSON.stringify({
100
+ module: 'CommonJS',
101
+ moduleResolution: 'Node10',
102
+ customConditions: null,
103
+ });
104
+ }
89
105
  targets[options.buildTargetName] = {
90
106
  command: `rspack build`,
91
- options: { cwd: projectRoot, args: ['--node-env=production'] },
107
+ options: {
108
+ cwd: projectRoot,
109
+ args: ['--node-env=production'],
110
+ env,
111
+ },
92
112
  cache: true,
93
113
  dependsOn: [`^${options.buildTargetName}`],
94
114
  inputs: 'production' in namedInputs
@@ -109,20 +129,25 @@ async function createRspackTargets(configFilePath, projectRoot, options, context
109
129
  outputs,
110
130
  };
111
131
  targets[options.serveTargetName] = {
132
+ continuous: true,
112
133
  command: `rspack serve`,
113
134
  options: {
114
135
  cwd: projectRoot,
115
136
  args: ['--node-env=development'],
137
+ env,
116
138
  },
117
139
  };
118
140
  targets[options.previewTargetName] = {
141
+ continuous: true,
119
142
  command: `rspack serve`,
120
143
  options: {
121
144
  cwd: projectRoot,
122
145
  args: ['--node-env=production'],
146
+ env,
123
147
  },
124
148
  };
125
149
  targets[options.serveStaticTargetName] = {
150
+ continuous: true,
126
151
  executor: '@nx/web:file-server',
127
152
  options: {
128
153
  buildTarget: options.buildTargetName,
@@ -13,6 +13,7 @@ const nx_tsconfig_paths_rspack_plugin_1 = require("./plugins/nx-tsconfig-paths-r
13
13
  const get_terser_ecma_version_1 = require("./get-terser-ecma-version");
14
14
  const nodeExternals = require("webpack-node-externals");
15
15
  const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
16
+ const is_lib_buildable_1 = require("./is-lib-buildable");
16
17
  const IGNORED_RSPACK_WARNINGS = [
17
18
  /The comment file/i,
18
19
  /could not find any license/i,
@@ -42,7 +43,7 @@ function applyNxIndependentConfig(options, config) {
42
43
  config.node = false;
43
44
  config.mode =
44
45
  // When the target is Node avoid any optimizations, such as replacing `process.env.NODE_ENV` with build time value.
45
- config.target === 'node'
46
+ config.target === 'node' || config.target === 'async-node'
46
47
  ? 'none'
47
48
  : // Otherwise, make sure it matches `process.env.NODE_ENV`.
48
49
  // When mode is development or production, rspack will automatically
@@ -59,13 +60,20 @@ function applyNxIndependentConfig(options, config) {
59
60
  : 'none');
60
61
  // When target is Node, the Webpack mode will be set to 'none' which disables in memory caching and causes a full rebuild on every change.
61
62
  // So to mitigate this we enable in memory caching when target is Node and in watch mode.
62
- config.cache = options.target === 'node' && options.watch ? true : undefined;
63
+ config.cache =
64
+ (options.target === 'node' || options.target === 'async-node') &&
65
+ options.watch
66
+ ? true
67
+ : undefined;
63
68
  config.devtool =
64
69
  options.sourceMap === true ? 'source-map' : options.sourceMap;
65
70
  config.output = {
66
71
  ...(config.output ?? {}),
67
- libraryTarget: config.output?.libraryTarget ??
68
- (options.target === 'node' ? 'commonjs' : undefined),
72
+ libraryTarget: options.target === 'node'
73
+ ? 'commonjs'
74
+ : options.target === 'async-node'
75
+ ? 'commonjs-module'
76
+ : undefined,
69
77
  path: config.output?.path ??
70
78
  (options.outputPath
71
79
  ? // If path is relative, it is relative from project root (aka cwd).
@@ -81,7 +89,7 @@ function applyNxIndependentConfig(options, config) {
81
89
  hashFunction: config.output?.hashFunction ?? 'xxhash64',
82
90
  // Disabled for performance
83
91
  pathinfo: config.output?.pathinfo ?? false,
84
- clean: options.deleteOutputPath,
92
+ clean: config.output?.clean ?? options.deleteOutputPath,
85
93
  };
86
94
  config.watch = options.watch;
87
95
  config.watchOptions = {
@@ -177,15 +185,18 @@ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
177
185
  if (options.useTsconfigPaths) {
178
186
  plugins.push(new nx_tsconfig_paths_rspack_plugin_1.NxTsconfigPathsRspackPlugin({ ...options, tsConfig }));
179
187
  }
180
- // New TS Solution already has a typecheck target
181
- if (!options?.skipTypeChecking && !isUsingTsSolution) {
182
- const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
183
- plugins.push(new ForkTsCheckerWebpackPlugin({
188
+ // New TS Solution already has a typecheck target but allow it to run during serve
189
+ if ((!options?.skipTypeChecking && !isUsingTsSolution) ||
190
+ (isUsingTsSolution &&
191
+ options?.skipTypeChecking === false &&
192
+ process.env['WEBPACK_SERVE'])) {
193
+ const { TsCheckerRspackPlugin } = require('ts-checker-rspack-plugin');
194
+ plugins.push(new TsCheckerRspackPlugin({
184
195
  typescript: {
185
196
  configFile: path.isAbsolute(tsConfig)
186
197
  ? tsConfig
187
198
  : path.join(options.root, tsConfig),
188
- memoryLimit: options.memoryLimit || 2018,
199
+ memoryLimit: options.memoryLimit || 8192, // default memory limit is 8192
189
200
  },
190
201
  }));
191
202
  }
@@ -263,9 +274,34 @@ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
263
274
  plugins.push(new stats_json_plugin_1.StatsJsonPlugin());
264
275
  }
265
276
  const externals = [];
266
- if (options.target === 'node' && options.externalDependencies === 'all') {
277
+ if ((options.target === 'node' || options.target === 'async-node') &&
278
+ options.externalDependencies === 'all') {
267
279
  const modulesDir = `${options.root}/node_modules`;
268
- externals.push(nodeExternals({ modulesDir }));
280
+ const graph = options.projectGraph;
281
+ const projectName = options.projectName;
282
+ const deps = graph?.dependencies?.[projectName] ?? [];
283
+ // Collect non-buildable TS project references so that they are bundled
284
+ // in the final output. This is needed for projects that are not buildable
285
+ // but are referenced by buildable projects. This is needed for the new TS
286
+ // solution setup.
287
+ const nonBuildableWorkspaceLibs = isUsingTsSolution
288
+ ? deps
289
+ .filter((dep) => {
290
+ const node = graph.nodes?.[dep.target];
291
+ if (!node || node.type !== 'lib')
292
+ return false;
293
+ const hasBuildTarget = 'build' in (node.data?.targets ?? {});
294
+ if (hasBuildTarget) {
295
+ return false;
296
+ }
297
+ // If there is no build target we check the package exports to see if they reference
298
+ // source files
299
+ return !(0, is_lib_buildable_1.isBuildableLibrary)(node);
300
+ })
301
+ .map((dep) => graph.nodes?.[dep.target]?.data?.metadata?.js?.packageName)
302
+ .filter((name) => !!name)
303
+ : [];
304
+ externals.push(nodeExternals({ modulesDir, allowlist: nonBuildableWorkspaceLibs }));
269
305
  }
270
306
  else if (Array.isArray(options.externalDependencies)) {
271
307
  externals.push(function (ctx, callback) {
@@ -333,6 +369,8 @@ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
333
369
  tsx: true,
334
370
  },
335
371
  transform: {
372
+ legacyDecorator: true,
373
+ decoratorMetadata: true,
336
374
  react: {
337
375
  runtime: 'automatic',
338
376
  pragma: 'React.createElement',
@@ -54,6 +54,8 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
54
54
  const globalStylePaths = [];
55
55
  // Determine hashing format.
56
56
  const hashFormat = (0, hash_format_1.getOutputHashFormat)(options.outputHashing);
57
+ const sassOptions = options.stylePreprocessorOptions?.sassOptions;
58
+ const lessOptions = options.stylePreprocessorOptions?.lessOptions;
57
59
  const includePaths = [];
58
60
  if (options?.stylePreprocessorOptions?.includePaths?.length > 0) {
59
61
  options.stylePreprocessorOptions.includePaths.forEach((includePath) => includePaths.push((0, path_1.resolve)(options.root, includePath)));
@@ -88,11 +90,15 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
88
90
  {
89
91
  loader: require.resolve('sass-loader'),
90
92
  options: {
91
- implementation: require('sass'),
93
+ implementation: options.sassImplementation === 'sass-embedded'
94
+ ? require.resolve('sass-embedded')
95
+ : require.resolve('sass'),
96
+ api: 'modern-compiler',
92
97
  sassOptions: {
93
98
  fiber: false,
94
99
  precision: 8,
95
100
  includePaths,
101
+ ...(sassOptions ?? {}),
96
102
  },
97
103
  },
98
104
  },
@@ -108,6 +114,7 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
108
114
  options: {
109
115
  lessOptions: {
110
116
  paths: includePaths,
117
+ ...(lessOptions ?? {}),
111
118
  },
112
119
  },
113
120
  },
@@ -143,13 +150,17 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
143
150
  {
144
151
  loader: require.resolve('sass-loader'),
145
152
  options: {
146
- implementation: require('sass'),
153
+ api: 'modern-compiler',
154
+ implementation: options.sassImplementation === 'sass-embedded'
155
+ ? require.resolve('sass-embedded')
156
+ : require.resolve('sass'),
147
157
  sourceMap: !!options.sourceMap,
148
158
  sassOptions: {
149
159
  fiber: false,
150
160
  // bootstrap-sass requires a minimum precision of 8
151
161
  precision: 8,
152
162
  includePaths,
163
+ ...(sassOptions ?? {}),
153
164
  },
154
165
  },
155
166
  },
@@ -167,6 +178,7 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
167
178
  lessOptions: {
168
179
  javascriptEnabled: true,
169
180
  ...lessPathOptions,
181
+ ...(lessOptions ?? {}),
170
182
  },
171
183
  },
172
184
  },
@@ -203,13 +215,17 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
203
215
  {
204
216
  loader: require.resolve('sass-loader'),
205
217
  options: {
206
- implementation: require('sass'),
218
+ api: 'modern-compiler',
219
+ implementation: options.sassImplementation === 'sass-embedded'
220
+ ? require.resolve('sass-embedded')
221
+ : require.resolve('sass'),
207
222
  sourceMap: !!options.sourceMap,
208
223
  sassOptions: {
209
224
  fiber: false,
210
225
  // bootstrap-sass requires a minimum precision of 8
211
226
  precision: 8,
212
227
  includePaths,
228
+ ...(sassOptions ?? {}),
213
229
  },
214
230
  },
215
231
  },
@@ -227,6 +243,7 @@ function applyWebConfig(options, config = {}, { useNormalizedEntry, } = {}) {
227
243
  lessOptions: {
228
244
  javascriptEnabled: true,
229
245
  ...lessPathOptions,
246
+ ...(lessOptions ?? {}),
230
247
  },
231
248
  },
232
249
  },
@@ -0,0 +1,7 @@
1
+ import { type ProjectGraphProjectNode } from '@nx/devkit';
2
+ /**
3
+ * Check if the library is buildable.
4
+ * @param node from the project graph
5
+ * @returns boolean
6
+ */
7
+ export declare function isBuildableLibrary(node: ProjectGraphProjectNode): boolean;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isBuildableLibrary = isBuildableLibrary;
4
+ function isSourceFile(path) {
5
+ return ['.ts', '.tsx', '.mts', '.cts'].some((ext) => path.endsWith(ext));
6
+ }
7
+ function isBuildableExportMap(packageExports) {
8
+ if (!packageExports || Object.keys(packageExports).length === 0) {
9
+ return false; // exports = {} → not buildable
10
+ }
11
+ const isCompiledExport = (value) => {
12
+ if (typeof value === 'string') {
13
+ return !isSourceFile(value);
14
+ }
15
+ if (typeof value === 'object' && value !== null) {
16
+ return Object.entries(value).some(([key, subValue]) => {
17
+ if (key === 'types' ||
18
+ key === 'development' ||
19
+ key === './package.json')
20
+ return false;
21
+ return typeof subValue === 'string' && !isSourceFile(subValue);
22
+ });
23
+ }
24
+ return false;
25
+ };
26
+ if (packageExports['.']) {
27
+ return isCompiledExport(packageExports['.']);
28
+ }
29
+ return Object.entries(packageExports).some(([key, value]) => key !== '.' && isCompiledExport(value));
30
+ }
31
+ /**
32
+ * Check if the library is buildable.
33
+ * @param node from the project graph
34
+ * @returns boolean
35
+ */
36
+ function isBuildableLibrary(node) {
37
+ if (!node.data.metadata?.js) {
38
+ return false;
39
+ }
40
+ const { packageExports, packageMain } = node.data.metadata.js;
41
+ // if we have exports only check this else fallback to packageMain
42
+ if (packageExports) {
43
+ return isBuildableExportMap(packageExports);
44
+ }
45
+ return (typeof packageMain === 'string' &&
46
+ packageMain !== '' &&
47
+ !isSourceFile(packageMain));
48
+ }
@@ -99,7 +99,7 @@ function postcssOptionsCreator(options, { includePaths, forCssModules = false, }
99
99
  ? []
100
100
  : [
101
101
  (0, postcss_cli_resources_1.PostcssCliResources)({
102
- baseHref: options.baseHref,
102
+ baseHref: options.baseHref ? options.baseHref : undefined,
103
103
  deployUrl: options.deployUrl,
104
104
  loader,
105
105
  filename: `[name]${hashFormat.file}.[ext]`,
@@ -55,7 +55,7 @@ export interface NxAppRspackPluginOptions {
55
55
  /**
56
56
  * Set <base href> for the resulting index.html.
57
57
  */
58
- baseHref?: string;
58
+ baseHref?: string | false;
59
59
  /**
60
60
  * Build the libraries from source. Default is `true`.
61
61
  */
@@ -63,6 +63,7 @@ export interface NxAppRspackPluginOptions {
63
63
  commonChunk?: boolean;
64
64
  /**
65
65
  * Delete the output path before building.
66
+ * @deprecated Use the `output.clean` option in Rspack. https://rspack.dev/config/output#outputclean
66
67
  */
67
68
  deleteOutputPath?: boolean;
68
69
  /**
@@ -148,6 +149,10 @@ export interface NxAppRspackPluginOptions {
148
149
  * Add an additional chunk for the rspack runtime. Defaults to `true` when `target === 'web'`.
149
150
  */
150
151
  runtimeChunk?: boolean;
152
+ /**
153
+ * The implementation of the SASS compiler to use. Can be either `sass` or `sass-embedded`. Defaults to `sass-embedded`.
154
+ */
155
+ sassImplementation?: 'sass' | 'sass-embedded';
151
156
  /**
152
157
  * External scripts that will be included before the main application entry.
153
158
  */
@@ -183,7 +188,11 @@ export interface NxAppRspackPluginOptions {
183
188
  /**
184
189
  * Options for the style preprocessor. e.g. `{ "includePaths": [] }` for SASS.
185
190
  */
186
- stylePreprocessorOptions?: any;
191
+ stylePreprocessorOptions?: {
192
+ includePaths?: string[];
193
+ sassOptions?: Record<string, any>;
194
+ lessOptions?: Record<string, any>;
195
+ };
187
196
  /**
188
197
  * External stylesheets that will be included with the application.
189
198
  */
@@ -77,6 +77,7 @@ function normalizeOptions(options) {
77
77
  projectRoot: projectNode.data.root,
78
78
  root: devkit_1.workspaceRoot,
79
79
  runtimeChunk: combinedPluginAndMaybeExecutorOptions.runtimeChunk ?? true,
80
+ sassImplementation: combinedPluginAndMaybeExecutorOptions.sassImplementation ?? 'sass',
80
81
  scripts: combinedPluginAndMaybeExecutorOptions.scripts ?? [],
81
82
  sourceMap: combinedPluginAndMaybeExecutorOptions.sourceMap ?? !isProd,
82
83
  sourceRoot,
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export declare function getRspackE2EWebServerInfo(tree: Tree, projectName: string, configFilePath: string, isPluginBeingAdded: boolean, e2ePortOverride?: number): Promise<import("@nx/devkit/src/generators/e2e-web-server-info-utils").E2EWebServerDetails>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRspackE2EWebServerInfo = getRspackE2EWebServerInfo;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const e2e_web_server_info_utils_1 = require("@nx/devkit/src/generators/e2e-web-server-info-utils");
6
+ async function getRspackE2EWebServerInfo(tree, projectName, configFilePath, isPluginBeingAdded, e2ePortOverride) {
7
+ const nxJson = (0, devkit_1.readNxJson)(tree);
8
+ let e2ePort = e2ePortOverride ?? 4200;
9
+ if (nxJson.targetDefaults?.['serve'] &&
10
+ nxJson.targetDefaults?.['serve'].options?.port) {
11
+ e2ePort = nxJson.targetDefaults?.['serve'].options?.port;
12
+ }
13
+ return (0, e2e_web_server_info_utils_1.getE2EWebServerInfo)(tree, projectName, {
14
+ plugin: '@nx/rspack/plugin',
15
+ serveTargetName: 'serveTargetName',
16
+ serveStaticTargetName: 'previewTargetName',
17
+ configFilePath,
18
+ }, {
19
+ defaultServeTargetName: 'serve',
20
+ defaultServeStaticTargetName: 'preview',
21
+ defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
22
+ defaultE2ECiBaseUrl: 'http://localhost:4200',
23
+ defaultE2EPort: e2ePort,
24
+ }, isPluginBeingAdded);
25
+ }
@@ -1,16 +1,16 @@
1
1
  export declare const nxVersion: any;
2
- export declare const rspackCoreVersion = "^1.1.5";
2
+ export declare const rspackCoreVersion = "1.2.2";
3
3
  export declare const rspackDevServerVersion = "1.0.9";
4
- export declare const rspackPluginMinifyVersion = "^0.7.5";
5
4
  export declare const rspackPluginReactRefreshVersion = "^1.0.0";
6
5
  export declare const lessLoaderVersion = "~11.1.3";
6
+ export declare const sassLoaderVersion = "^16.0.4";
7
+ export declare const sassEmbeddedVersion = "^1.83.4";
7
8
  export declare const reactRefreshVersion = "~0.14.0";
8
9
  export declare const nestjsCommonVersion = "~9.0.0";
9
10
  export declare const nestjsCoreVersion = "~9.0.0";
10
11
  export declare const nestjsPlatformExpressVersion = "~9.0.0";
11
12
  export declare const nestjsMicroservicesVersion = "~9.0.0";
12
13
  export declare const lessVersion = "4.1.3";
13
- export declare const sassVersion = "^1.42.1";
14
14
  export declare const stylusVersion = "^0.55.0";
15
15
  export declare const eslintPluginImportVersion = "2.27.5";
16
16
  export declare const eslintPluginJsxA11yVersion = "6.7.1";
@@ -1,19 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.eslintPluginReactHooksVersion = exports.eslintPluginReactVersion = exports.eslintPluginJsxA11yVersion = exports.eslintPluginImportVersion = exports.stylusVersion = exports.sassVersion = exports.lessVersion = exports.nestjsMicroservicesVersion = exports.nestjsPlatformExpressVersion = exports.nestjsCoreVersion = exports.nestjsCommonVersion = exports.reactRefreshVersion = exports.lessLoaderVersion = exports.rspackPluginReactRefreshVersion = exports.rspackPluginMinifyVersion = exports.rspackDevServerVersion = exports.rspackCoreVersion = exports.nxVersion = void 0;
3
+ exports.eslintPluginReactHooksVersion = exports.eslintPluginReactVersion = exports.eslintPluginJsxA11yVersion = exports.eslintPluginImportVersion = exports.stylusVersion = exports.lessVersion = exports.nestjsMicroservicesVersion = exports.nestjsPlatformExpressVersion = exports.nestjsCoreVersion = exports.nestjsCommonVersion = exports.reactRefreshVersion = exports.sassEmbeddedVersion = exports.sassLoaderVersion = exports.lessLoaderVersion = exports.rspackPluginReactRefreshVersion = exports.rspackDevServerVersion = exports.rspackCoreVersion = exports.nxVersion = void 0;
4
4
  exports.nxVersion = require('../../package.json').version;
5
- exports.rspackCoreVersion = '^1.1.5';
5
+ exports.rspackCoreVersion = '1.2.2';
6
6
  exports.rspackDevServerVersion = '1.0.9';
7
- exports.rspackPluginMinifyVersion = '^0.7.5';
8
7
  exports.rspackPluginReactRefreshVersion = '^1.0.0';
9
8
  exports.lessLoaderVersion = '~11.1.3';
9
+ exports.sassLoaderVersion = '^16.0.4';
10
+ exports.sassEmbeddedVersion = '^1.83.4';
10
11
  exports.reactRefreshVersion = '~0.14.0';
11
12
  exports.nestjsCommonVersion = '~9.0.0';
12
13
  exports.nestjsCoreVersion = '~9.0.0';
13
14
  exports.nestjsPlatformExpressVersion = '~9.0.0';
14
15
  exports.nestjsMicroservicesVersion = '~9.0.0';
15
16
  exports.lessVersion = '4.1.3';
16
- exports.sassVersion = '^1.42.1';
17
17
  exports.stylusVersion = '^0.55.0';
18
18
  exports.eslintPluginImportVersion = '2.27.5';
19
19
  exports.eslintPluginJsxA11yVersion = '6.7.1';
@@ -8,10 +8,13 @@ export interface WithWebOptions {
8
8
  generateIndexHtml?: boolean;
9
9
  index?: string;
10
10
  postcssConfig?: string;
11
+ sassImplementation?: 'sass' | 'sass-embedded';
11
12
  scripts?: Array<ExtraEntryPointClass | string>;
12
13
  styles?: Array<ExtraEntryPointClass | string>;
13
14
  stylePreprocessorOptions?: {
14
15
  includePaths?: string[];
16
+ sassOptions?: Record<string, any>;
17
+ lessOptions?: Record<string, any>;
15
18
  };
16
19
  cssModules?: boolean;
17
20
  ssr?: boolean;