@nx/rspack 23.0.0 → 23.1.0-beta.1

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 (40) hide show
  1. package/README.md +1 -2
  2. package/dist/src/executors/rspack/lib/config.js +2 -2
  3. package/dist/src/executors/rspack/rspack.impl.js +3 -4
  4. package/dist/src/executors/ssr-dev-server/ssr-dev-server.impl.d.ts +1 -1
  5. package/dist/src/generators/configuration/configuration.js +1 -3
  6. package/dist/src/migrations/update-23-0-0/migrate-rspack-config-to-v2.d.ts +5 -0
  7. package/dist/src/migrations/update-23-0-0/migrate-rspack-config-to-v2.js +163 -0
  8. package/dist/src/migrations/update-23-0-0/rewrite-experiments-css-to-module-rules.md +96 -0
  9. package/dist/src/plugins/generate-package-json-plugin.d.ts +1 -1
  10. package/dist/src/plugins/generate-package-json-plugin.js +5 -5
  11. package/dist/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.js +2 -0
  12. package/dist/src/plugins/nx-react-rspack-plugin/nx-react-rspack-plugin.js +2 -1
  13. package/dist/src/plugins/utils/apply-base-config.d.ts +3 -2
  14. package/dist/src/plugins/utils/apply-base-config.js +56 -35
  15. package/dist/src/plugins/utils/apply-react-config.d.ts +13 -2
  16. package/dist/src/plugins/utils/apply-react-config.js +33 -7
  17. package/dist/src/plugins/utils/apply-web-config.d.ts +3 -2
  18. package/dist/src/plugins/utils/apply-web-config.js +23 -16
  19. package/dist/src/plugins/utils/loaders/stylesheet-loaders.d.ts +14 -14
  20. package/dist/src/plugins/utils/loaders/stylesheet-loaders.js +6 -7
  21. package/dist/src/plugins/utils/plugins/generate-package-json-plugin.d.ts +1 -1
  22. package/dist/src/plugins/utils/plugins/generate-package-json-plugin.js +5 -5
  23. package/dist/src/plugins/utils/plugins/nx-tsconfig-paths-rspack-plugin.d.ts +1 -1
  24. package/dist/src/plugins/utils/plugins/scripts-rspack-plugin.d.ts +1 -1
  25. package/dist/src/plugins/utils/plugins/scripts-rspack-plugin.js +9 -8
  26. package/dist/src/plugins/utils/plugins/stats-json-plugin.d.ts +1 -1
  27. package/dist/src/plugins/utils/plugins/stats-json-plugin.js +2 -2
  28. package/dist/src/plugins/write-index-html-plugin.d.ts +1 -1
  29. package/dist/src/plugins/write-index-html-plugin.js +7 -8
  30. package/dist/src/utils/create-compiler.d.ts +1 -1
  31. package/dist/src/utils/is-serve-mode.d.ts +1 -0
  32. package/dist/src/utils/is-serve-mode.js +8 -0
  33. package/dist/src/utils/mode-utils.d.ts +1 -1
  34. package/dist/src/utils/read-rspack-options.d.ts +1 -1
  35. package/dist/src/utils/version-utils.d.ts +1 -17
  36. package/dist/src/utils/version-utils.js +6 -17
  37. package/dist/src/utils/versions.d.ts +1 -1
  38. package/dist/src/utils/versions.js +12 -8
  39. package/migrations.json +62 -0
  40. package/package.json +12 -12
package/README.md CHANGED
@@ -7,13 +7,12 @@
7
7
 
8
8
  <div style="text-align: center;">
9
9
 
10
- [![CircleCI](https://circleci.com/gh/nrwl/nx.svg?style=svg)](https://circleci.com/gh/nrwl/nx)
11
10
  [![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)]()
12
11
  [![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
13
12
  [![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)]()
14
13
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
15
- [![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
16
14
  [![Join us on the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
15
+ [![Nx Sandboxing](https://staging.nx.app/workspaces/62d013ea0852fe0a2df74438/sandbox-badge.svg)](https://nx.dev/docs/features/ci-features/sandboxing)
17
16
 
18
17
  </div>
19
18
 
@@ -18,8 +18,8 @@ async function getRspackConfigs(options, context) {
18
18
  }
19
19
  // Nx composes these helpers internally to build the default config; suppress
20
20
  // their deprecation warning so it fires only for user-authored configs.
21
- const config = (0, deprecation_1.suppressRspackComposeHelperWarnings)(() => (options.target === 'web'
22
- ? (0, config_1.composePluginsSync)((0, with_nx_1.withNx)(options), (0, with_web_1.withWeb)(options))
21
+ const config = await (0, deprecation_1.suppressRspackComposeHelperWarnings)(() => (options.target === 'web'
22
+ ? (0, config_1.composePlugins)((0, with_nx_1.withNx)(options), (0, with_web_1.withWeb)(options))
23
23
  : (0, with_nx_1.withNx)(options))({}, { options, context }));
24
24
  if (typeof userDefinedConfig === 'function' &&
25
25
  ((0, config_1.isNxRspackComposablePlugin)(userDefinedConfig) ||
@@ -5,7 +5,6 @@ const devkit_1 = require("@nx/devkit");
5
5
  const internal_1 = require("@nx/devkit/internal");
6
6
  const js_1 = require("@nx/js");
7
7
  const internal_2 = require("@nx/js/internal");
8
- const core_1 = require("@rspack/core");
9
8
  const path_1 = require("path");
10
9
  const create_compiler_1 = require("../../utils/create-compiler");
11
10
  const mode_utils_1 = require("../../utils/mode-utils");
@@ -26,9 +25,9 @@ async function* runExecutor(options, context) {
26
25
  }
27
26
  const compiler = await (0, create_compiler_1.createCompiler)(normalizedOptions, context);
28
27
  const iterable = (0, internal_1.createAsyncIterable)(async ({ next, done }) => {
29
- const watch = (compiler instanceof core_1.Compiler
30
- ? compiler.options.watch
31
- : compiler.options[0].watch) ?? options.watch;
28
+ const watch = ((0, create_compiler_1.isMultiCompiler)(compiler)
29
+ ? compiler.options[0].watch
30
+ : compiler.options.watch) ?? options.watch;
32
31
  if (watch) {
33
32
  const watcher = compiler.watch({}, async (err, stats) => {
34
33
  if (err) {
@@ -1,8 +1,8 @@
1
1
  import { ExecutorContext } from '@nx/devkit';
2
2
  import { RspackSsrDevServerOptions, TargetOptions } from './schema';
3
3
  export declare function ssrDevServerExecutor(options: RspackSsrDevServerOptions, context: ExecutorContext): AsyncGenerator<{
4
- baseUrl: string;
5
4
  success: boolean;
6
5
  options: TargetOptions;
6
+ baseUrl: string;
7
7
  }, void, unknown>;
8
8
  export default ssrDevServerExecutor;
@@ -13,13 +13,11 @@ function projectIsRootProjectInStandaloneWorkspace(projectRoot) {
13
13
  return (0, path_1.relative)(devkit_1.workspaceRoot, projectRoot).length === 0;
14
14
  }
15
15
  function editTsConfig(tree, projectRoot, framework, relativePathToRootTsConfig) {
16
- const shared = require('@nx/js');
17
16
  if (framework === 'react') {
18
17
  const json = {
19
18
  compilerOptions: {
20
19
  jsx: 'react-jsx',
21
20
  allowJs: false,
22
- esModuleInterop: false,
23
21
  allowSyntheticDefaultImports: true,
24
22
  strict: true,
25
23
  },
@@ -35,7 +33,7 @@ function editTsConfig(tree, projectRoot, framework, relativePathToRootTsConfig)
35
33
  if (projectIsRootProjectInStandaloneWorkspace(projectRoot)) {
36
34
  json.compileOnSave = false;
37
35
  json.compilerOptions = {
38
- ...shared.tsConfigBaseOptions,
36
+ ...(0, internal_1.getTsConfigBaseOptions)(tree),
39
37
  ...json.compilerOptions,
40
38
  };
41
39
  json.exclude = ['node_modules', 'tmp'];
@@ -0,0 +1,5 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function migrateRspackConfigToV2(tree: Tree): Promise<void>;
3
+ export declare function rewriteLibraryTarget(source: string): string;
4
+ export declare function disableLazyCompilationForModuleFederation(source: string): string;
5
+ export declare function rewriteExperimentsCss(source: string): string;
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = migrateRspackConfigToV2;
4
+ exports.rewriteLibraryTarget = rewriteLibraryTarget;
5
+ exports.disableLazyCompilationForModuleFederation = disableLazyCompilationForModuleFederation;
6
+ exports.rewriteExperimentsCss = rewriteExperimentsCss;
7
+ const tslib_1 = require("tslib");
8
+ const devkit_1 = require("@nx/devkit");
9
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
10
+ const ts = tslib_1.__importStar(require("typescript"));
11
+ // Rewrite rspack.config.{js,ts,mjs,cjs} for @rspack/core@2:
12
+ // - output.libraryTarget → output.library.type
13
+ // - experiments.css: true dropped (default in v2); :false replaced with a comment
14
+ // - module federation configs get lazyCompilation: false (rspack-cli@2 dev
15
+ // mode enables it by default, which breaks federated remotes)
16
+ // See rspack.rs/guide/migration/rspack_1.x.
17
+ async function migrateRspackConfigToV2(tree) {
18
+ const configFiles = [];
19
+ (0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
20
+ if (filePath.endsWith('rspack.config.ts') ||
21
+ filePath.endsWith('rspack.config.js') ||
22
+ filePath.endsWith('rspack.config.mjs') ||
23
+ filePath.endsWith('rspack.config.cjs')) {
24
+ configFiles.push(filePath);
25
+ }
26
+ });
27
+ for (const configFile of configFiles) {
28
+ const original = tree.read(configFile, 'utf-8');
29
+ if (!original)
30
+ continue;
31
+ let next = rewriteLibraryTarget(original);
32
+ next = rewriteExperimentsCss(next);
33
+ next = disableLazyCompilationForModuleFederation(next);
34
+ if (next !== original) {
35
+ tree.write(configFile, next);
36
+ }
37
+ }
38
+ await (0, devkit_1.formatFiles)(tree);
39
+ }
40
+ function applyEdits(source, edits) {
41
+ if (edits.length === 0)
42
+ return source;
43
+ // Apply back-to-front so earlier edits don't shift later offsets.
44
+ const sorted = [...edits].sort((a, b) => b.start - a.start);
45
+ return sorted.reduce((acc, e) => acc.slice(0, e.start) + e.replacement + acc.slice(e.end), source);
46
+ }
47
+ function getPropertyName(prop) {
48
+ const name = prop.name;
49
+ if (ts.isIdentifier(name))
50
+ return name.text;
51
+ if (ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name)) {
52
+ return name.text;
53
+ }
54
+ return undefined;
55
+ }
56
+ function isInsideObjectKeyed(prop, parentKey) {
57
+ const objLiteral = prop.parent;
58
+ if (!objLiteral || !ts.isObjectLiteralExpression(objLiteral))
59
+ return false;
60
+ const containingProp = objLiteral.parent;
61
+ if (!containingProp || !ts.isPropertyAssignment(containingProp))
62
+ return false;
63
+ return getPropertyName(containingProp) === parentKey;
64
+ }
65
+ function rewriteLibraryTarget(source) {
66
+ if (!source.includes('libraryTarget'))
67
+ return source;
68
+ const sourceFile = (0, tsquery_1.ast)(source);
69
+ const edits = [];
70
+ const visit = (node) => {
71
+ if (ts.isPropertyAssignment(node) &&
72
+ getPropertyName(node) === 'libraryTarget' &&
73
+ isInsideObjectKeyed(node, 'output') &&
74
+ isStringLikeInitializer(node.initializer)) {
75
+ const valueText = node.initializer.getText(sourceFile);
76
+ edits.push({
77
+ start: node.getStart(sourceFile),
78
+ end: node.getEnd(),
79
+ replacement: `library: { type: ${valueText} }`,
80
+ });
81
+ }
82
+ ts.forEachChild(node, visit);
83
+ };
84
+ visit(sourceFile);
85
+ return applyEdits(source, edits);
86
+ }
87
+ function isStringLikeInitializer(node) {
88
+ return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node);
89
+ }
90
+ // rspack-cli@2 dev mode enables lazyCompilation unless the config sets it
91
+ // explicitly, and lazy-compiled dynamic imports break module federation
92
+ // remotes. Insert `lazyCompilation: false` into plain-object configs that use
93
+ // module federation. Compose-style configs (withModuleFederation) are handled
94
+ // at runtime by withModuleFederation itself.
95
+ function disableLazyCompilationForModuleFederation(source) {
96
+ if (!source.includes('NxModuleFederationPlugin') &&
97
+ !source.includes('ModuleFederationPlugin')) {
98
+ return source;
99
+ }
100
+ if (source.includes('lazyCompilation'))
101
+ return source;
102
+ const sourceFile = (0, tsquery_1.ast)(source);
103
+ const edits = [];
104
+ const insertIntoObject = (obj) => {
105
+ const start = obj.getStart(sourceFile) + 1;
106
+ edits.push({
107
+ start,
108
+ end: start,
109
+ replacement: '\n // rspack-cli dev mode defaults this on; it breaks module federation.\n lazyCompilation: false,',
110
+ });
111
+ };
112
+ const visit = (node) => {
113
+ // export default { ... }
114
+ if (ts.isExportAssignment(node) &&
115
+ ts.isObjectLiteralExpression(node.expression)) {
116
+ insertIntoObject(node.expression);
117
+ return;
118
+ }
119
+ // module.exports = { ... }
120
+ if (ts.isBinaryExpression(node) &&
121
+ node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
122
+ ts.isObjectLiteralExpression(node.right) &&
123
+ node.left.getText(sourceFile) === 'module.exports') {
124
+ insertIntoObject(node.right);
125
+ return;
126
+ }
127
+ ts.forEachChild(node, visit);
128
+ };
129
+ visit(sourceFile);
130
+ return applyEdits(source, edits);
131
+ }
132
+ // `experiments.css: true` is left for the companion AI-prompt migration
133
+ // `rewrite-experiments-css-to-module-rules` to handle.
134
+ function rewriteExperimentsCss(source) {
135
+ if (!/\bcss\s*:/.test(source))
136
+ return source;
137
+ const sourceFile = (0, tsquery_1.ast)(source);
138
+ const edits = [];
139
+ const visit = (node) => {
140
+ if (ts.isPropertyAssignment(node) &&
141
+ getPropertyName(node) === 'css' &&
142
+ isInsideObjectKeyed(node, 'experiments') &&
143
+ node.initializer.kind === ts.SyntaxKind.FalseKeyword) {
144
+ // Delete the property + its trailing comma and newline so the
145
+ // surrounding object literal stays well-formed.
146
+ let endOfRemoval = node.getEnd();
147
+ const trailingText = source.slice(endOfRemoval);
148
+ const trailingMatch = trailingText.match(/^\s*,?\s*\r?\n/);
149
+ if (trailingMatch) {
150
+ endOfRemoval += trailingMatch[0].length;
151
+ }
152
+ let startOfRemoval = node.getStart(sourceFile);
153
+ const lineStart = source.lastIndexOf('\n', startOfRemoval - 1) + 1;
154
+ if (source.slice(lineStart, startOfRemoval).trim() === '') {
155
+ startOfRemoval = lineStart;
156
+ }
157
+ edits.push({ start: startOfRemoval, end: endOfRemoval, replacement: '' });
158
+ }
159
+ ts.forEachChild(node, visit);
160
+ };
161
+ visit(sourceFile);
162
+ return applyEdits(source, edits);
163
+ }
@@ -0,0 +1,96 @@
1
+ #### Rewrite `experiments.css: true` for `@rspack/core@2`
2
+
3
+ `@rspack/core@2` removed `experiments.css` and promoted CSS handling to a
4
+ default-available feature — but it's now opt-in **per file type** via
5
+ `module.rules`. Workspaces that set `experiments.css: true` on v1 will
6
+ silently lose CSS processing on v2 unless `module.rules` declares a rule
7
+ matching their CSS file extensions with a `type` of `'css'`, `'css/module'`,
8
+ or `'css/auto'`.
9
+
10
+ This change is workspace-specific (which `test:` regex, which `type:`,
11
+ whether existing rules already cover it), so the migration ships as an
12
+ AI-assisted instruction rather than a blind codemod.
13
+
14
+ #### What needs to change
15
+
16
+ For every `rspack.config.{ts,js,mjs,cjs}` in the workspace that has
17
+ `experiments.css: true`:
18
+
19
+ 1. **Delete the `experiments.css: true` line.** If `experiments` becomes
20
+ empty after the deletion, delete the whole `experiments: { ... }`
21
+ property too.
22
+
23
+ 2. **Ensure `module.rules` has a CSS rule using `type: 'css/auto'`** (or
24
+ `'css'` / `'css/module'` if you have a stronger preference). The rspack
25
+ docs recommend `'css/auto'` because it auto-detects CSS Modules
26
+ (filenames matching `*.module.css`).
27
+ - If `module.rules` already has an entry that matches `.css` files —
28
+ for example via `css-loader` / `style-loader` / `MiniCssExtractPlugin`
29
+ — **leave it alone**. The user opted into a loader pipeline on v1 and
30
+ that pipeline still works on v2.
31
+
32
+ - If `module.rules` has no CSS-related rule at all, append:
33
+
34
+ ```ts
35
+ {
36
+ test: /\.css$/,
37
+ type: 'css/auto',
38
+ }
39
+ ```
40
+
41
+ 3. **Do not touch `experiments.css: false` configs.** Those are handled
42
+ automatically by the deterministic codemod that runs alongside this
43
+ prompt.
44
+
45
+ #### Sample Code Changes
46
+
47
+ ##### Before
48
+
49
+ ```ts title="apps/myapp/rspack.config.ts" {3-5}
50
+ export default {
51
+ // ...
52
+ experiments: {
53
+ css: true,
54
+ },
55
+ };
56
+ ```
57
+
58
+ ##### After
59
+
60
+ ```ts title="apps/myapp/rspack.config.ts" {3-7}
61
+ export default {
62
+ // ...
63
+ module: {
64
+ rules: [{ test: /\.css$/, type: 'css/auto' }],
65
+ },
66
+ };
67
+ ```
68
+
69
+ ##### Before — workspace that already uses css-loader
70
+
71
+ ```ts title="apps/myapp/rspack.config.ts" {3-5,7-10}
72
+ export default {
73
+ // ...
74
+ experiments: {
75
+ css: true,
76
+ },
77
+ module: {
78
+ rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader'] }],
79
+ },
80
+ };
81
+ ```
82
+
83
+ ##### After — `experiments.css` removed, existing rule untouched
84
+
85
+ ```ts title="apps/myapp/rspack.config.ts"
86
+ export default {
87
+ // ...
88
+ module: {
89
+ rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader'] }],
90
+ },
91
+ };
92
+ ```
93
+
94
+ #### Reference
95
+
96
+ [`@rspack/core@2` migration guide — Remove experiments.css](https://rspack.rs/guide/migration/rspack_1.x#remove-experimentscss)
@@ -1,5 +1,5 @@
1
1
  import { ExecutorContext } from '@nx/devkit';
2
- import { type Compiler, type RspackPluginInstance } from '@rspack/core';
2
+ import type { Compiler, RspackPluginInstance } from '@rspack/core';
3
3
  export declare class GeneratePackageJsonPlugin implements RspackPluginInstance {
4
4
  private readonly options;
5
5
  private readonly context;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GeneratePackageJsonPlugin = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const js_1 = require("@nx/js");
6
- const core_1 = require("@rspack/core");
7
6
  const pluginName = 'GeneratePackageJsonPlugin';
8
7
  class GeneratePackageJsonPlugin {
9
8
  constructor(options, context) {
@@ -13,10 +12,11 @@ class GeneratePackageJsonPlugin {
13
12
  }
14
13
  apply(compiler) {
15
14
  compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
16
- compilation.hooks.processAssets.tap({
15
+ compilation.hooks.processAssets.tapPromise({
17
16
  name: pluginName,
18
17
  stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
19
- }, () => {
18
+ }, async () => {
19
+ const sources = compiler.webpack.sources;
20
20
  const helperDependencies = (0, js_1.getHelperDependenciesFromProjectGraph)(this.context.root, this.context.projectName, this.projectGraph);
21
21
  const importHelpers = !!(0, js_1.readTsConfig)(this.options.tsConfig).options
22
22
  .importHelpers;
@@ -36,7 +36,7 @@ class GeneratePackageJsonPlugin {
36
36
  helperDependencies: helperDependencies.map((dep) => dep.target),
37
37
  });
38
38
  packageJson.main = packageJson.main ?? this.options.outputFileName;
39
- compilation.emitAsset('package.json', new core_1.sources.RawSource((0, devkit_1.serializeJson)(packageJson)));
39
+ compilation.emitAsset('package.json', new sources.RawSource((0, devkit_1.serializeJson)(packageJson)));
40
40
  const packageManager = (0, devkit_1.detectPackageManager)(this.context.root);
41
41
  if (packageManager === 'bun') {
42
42
  compilation
@@ -44,7 +44,7 @@ class GeneratePackageJsonPlugin {
44
44
  .warn('Bun lockfile generation is not supported. Only package.json will be generated.');
45
45
  }
46
46
  else {
47
- compilation.emitAsset((0, js_1.getLockFileName)(packageManager), new core_1.sources.RawSource((0, js_1.createLockFile)(packageJson, this.projectGraph, packageManager)));
47
+ compilation.emitAsset((0, js_1.getLockFileName)(packageManager), new sources.RawSource((0, js_1.createLockFile)(packageJson, this.projectGraph, packageManager)));
48
48
  }
49
49
  });
50
50
  });
@@ -35,6 +35,7 @@ class NxAppRspackPlugin {
35
35
  }
36
36
  (0, apply_base_config_1.applyBaseConfig)(this.options, compiler.options, {
37
37
  useNormalizedEntry: true,
38
+ compiler,
38
39
  });
39
40
  if (compiler.options.target) {
40
41
  this.options.target = compiler.options.target;
@@ -42,6 +43,7 @@ class NxAppRspackPlugin {
42
43
  if (this.options.target === 'web' || this.options.target === 'webworker') {
43
44
  (0, apply_web_config_1.applyWebConfig)(this.options, compiler.options, {
44
45
  useNormalizedEntry: true,
46
+ compiler,
45
47
  });
46
48
  }
47
49
  }
@@ -7,7 +7,8 @@ class NxReactRspackPlugin {
7
7
  this.options = options;
8
8
  }
9
9
  apply(compiler) {
10
- (0, apply_react_config_1.applyReactConfig)(this.options, compiler.options);
10
+ (0, apply_react_config_1.applyReactConfigSync)(compiler.options);
11
+ (0, apply_react_config_1.applyReactHotReloadToCompiler)(compiler);
11
12
  }
12
13
  }
13
14
  exports.NxReactRspackPlugin = NxReactRspackPlugin;
@@ -1,5 +1,6 @@
1
- import { Configuration, RspackOptionsNormalized } from '@rspack/core';
1
+ import type { Compiler, Configuration, RspackOptionsNormalized } from '@rspack/core';
2
2
  import { NormalizedNxAppRspackPluginOptions } from './models';
3
- export declare function applyBaseConfig(options: NormalizedNxAppRspackPluginOptions, config?: Partial<RspackOptionsNormalized | Configuration>, { useNormalizedEntry, }?: {
3
+ export declare function applyBaseConfig(options: NormalizedNxAppRspackPluginOptions, config?: Partial<RspackOptionsNormalized | Configuration>, { useNormalizedEntry, compiler, }?: {
4
4
  useNormalizedEntry?: boolean;
5
+ compiler?: Compiler;
5
6
  }): void;
@@ -4,8 +4,8 @@ exports.applyBaseConfig = applyBaseConfig;
4
4
  const tslib_1 = require("tslib");
5
5
  const path = tslib_1.__importStar(require("path"));
6
6
  const license_webpack_plugin_1 = require("license-webpack-plugin");
7
- const core_1 = require("@rspack/core");
8
7
  const js_1 = require("@nx/js");
8
+ const version_utils_1 = require("../../utils/version-utils");
9
9
  const stats_json_plugin_1 = require("./plugins/stats-json-plugin");
10
10
  const generate_package_json_plugin_1 = require("./plugins/generate-package-json-plugin");
11
11
  const hash_format_1 = require("./hash-format");
@@ -14,6 +14,7 @@ const get_terser_ecma_version_1 = require("./get-terser-ecma-version");
14
14
  const nodeExternals = require("webpack-node-externals");
15
15
  const internal_1 = require("@nx/js/internal");
16
16
  const get_non_buildable_libs_1 = require("./get-non-buildable-libs");
17
+ const is_serve_mode_1 = require("../../utils/is-serve-mode");
17
18
  const IGNORED_RSPACK_WARNINGS = [
18
19
  /The comment file/i,
19
20
  /could not find any license/i,
@@ -26,7 +27,7 @@ const extensionAlias = {
26
27
  '.jsx': ['.tsx', '.jsx'],
27
28
  };
28
29
  const mainFields = ['module', 'main'];
29
- function applyBaseConfig(options, config = {}, { useNormalizedEntry, } = {}) {
30
+ function applyBaseConfig(options, config = {}, { useNormalizedEntry, compiler, } = {}) {
30
31
  // Defaults that was applied from executor schema previously.
31
32
  options.externalDependencies ??= 'all';
32
33
  options.fileReplacements ??= [];
@@ -34,15 +35,21 @@ function applyBaseConfig(options, config = {}, { useNormalizedEntry, } = {}) {
34
35
  options.transformers ??= [];
35
36
  options.progress ??= true;
36
37
  options.outputHashing ??= 'all';
37
- applyNxIndependentConfig(options, config);
38
+ // Lazy-require avoids loading @rspack/core (pure ESM in v2) at module
39
+ // parse time, so Jest can still load this file.
40
+ const rspackCore = compiler
41
+ ? compiler.rspack
42
+ : require('@rspack/core');
43
+ applyNxIndependentConfig(options, config, rspackCore);
38
44
  // Some of the options only work during actual tasks, not when reading the rspack config during CreateNodes.
39
45
  if (global.NX_GRAPH_CREATION)
40
46
  return;
41
- applyNxDependentConfig(options, config, { useNormalizedEntry });
47
+ applyNxDependentConfig(options, config, { useNormalizedEntry }, rspackCore);
42
48
  }
43
- function applyNxIndependentConfig(options, config) {
49
+ function applyNxIndependentConfig(options, config, rspackCore) {
50
+ const { SwcJsMinimizerRspackPlugin } = rspackCore;
44
51
  const isProd = process.env.NODE_ENV === 'production' || options.mode === 'production';
45
- const isDevServer = process.env['WEBPACK_SERVE'];
52
+ const isDevServer = (0, is_serve_mode_1.isServeMode)();
46
53
  const hashFormat = (0, hash_format_1.getOutputHashFormat)(options.outputHashing);
47
54
  config.context = path.join(options.root, options.projectRoot);
48
55
  config.target ??= options.target;
@@ -75,30 +82,40 @@ function applyNxIndependentConfig(options, config) {
75
82
  : undefined;
76
83
  config.devtool =
77
84
  options.sourceMap === true ? 'source-map' : options.sourceMap;
85
+ const existingOutputConfig = config.output;
86
+ const existingLibraryTarget = existingOutputConfig?.libraryTarget;
87
+ const existingLibraryType = typeof existingOutputConfig?.library === 'object' &&
88
+ 'type' in existingOutputConfig?.library
89
+ ? existingOutputConfig?.library?.type
90
+ : undefined;
91
+ const computedLibraryType = (() => {
92
+ if (existingLibraryType !== undefined)
93
+ return undefined;
94
+ if (existingLibraryTarget !== undefined)
95
+ return existingLibraryTarget;
96
+ if (options.target === 'node')
97
+ return 'commonjs';
98
+ if (options.target === 'async-node')
99
+ return 'commonjs-module';
100
+ return undefined;
101
+ })();
102
+ // @rspack/core@2 removed output.libraryTarget; emit library.type instead.
103
+ const installedRspackMajor = (0, version_utils_1.getRspackCoreMajorVersion)(rspackCore);
104
+ const existingLibrary = typeof config.output?.library === 'object' ? config.output.library : {};
105
+ const libraryOutput = computedLibraryType === undefined
106
+ ? {}
107
+ : installedRspackMajor >= 2
108
+ ? {
109
+ library: { ...existingLibrary, type: computedLibraryType },
110
+ libraryTarget: undefined,
111
+ }
112
+ : { libraryTarget: computedLibraryType };
113
+ if (existingLibraryType !== undefined) {
114
+ libraryOutput.libraryTarget = undefined;
115
+ }
78
116
  config.output = {
79
117
  ...(config.output ?? {}),
80
- libraryTarget: (() => {
81
- const existingOutputConfig = config.output;
82
- const existingLibraryTarget = existingOutputConfig?.libraryTarget;
83
- const existingLibraryType = typeof existingOutputConfig?.library === 'object' &&
84
- 'type' in existingOutputConfig?.library
85
- ? existingOutputConfig?.library?.type
86
- : undefined;
87
- // If user is using modern library.type, don't set the deprecated libraryTarget
88
- if (existingLibraryType !== undefined) {
89
- return undefined;
90
- }
91
- // If user has set libraryTarget explicitly, use it
92
- if (existingLibraryTarget !== undefined) {
93
- return existingLibraryTarget;
94
- }
95
- // Set defaults based on target when user hasn't configured anything
96
- if (options.target === 'node')
97
- return 'commonjs';
98
- if (options.target === 'async-node')
99
- return 'commonjs-module';
100
- return undefined;
101
- })(),
118
+ ...libraryOutput,
102
119
  path: config.output?.path ??
103
120
  (options.outputPath
104
121
  ? // If path is relative, it is relative from project root (aka cwd).
@@ -120,7 +137,11 @@ function applyNxIndependentConfig(options, config) {
120
137
  config.watchOptions = {
121
138
  poll: options.poll,
122
139
  };
123
- config.profile = options.statsJson;
140
+ // TODO(v24): drop once @rspack/core v1 is out of the support window.
141
+ // v2 removed top-level `profile`; Rsdoctor replaces it.
142
+ if (options.statsJson && installedRspackMajor < 2) {
143
+ config.profile = true;
144
+ }
124
145
  config.performance = {
125
146
  ...config.performance,
126
147
  hints: false,
@@ -138,7 +159,7 @@ function applyNxIndependentConfig(options, config) {
138
159
  ? !!options.optimization.scripts
139
160
  : !!options.optimization,
140
161
  minimizer: [
141
- new core_1.SwcJsMinimizerRspackPlugin({
162
+ new SwcJsMinimizerRspackPlugin({
142
163
  extractComments: false,
143
164
  minimizerOptions: {
144
165
  // this needs to be false to allow toplevel variables to be used in the global scope
@@ -198,7 +219,8 @@ function applyNxIndependentConfig(options, config) {
198
219
  config.plugins ??= [];
199
220
  config.externals ??= [];
200
221
  }
201
- function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
222
+ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}, rspackCore) {
223
+ const { ProgressPlugin, SwcJsMinimizerRspackPlugin, CopyRspackPlugin } = rspackCore;
202
224
  const tsConfig = options.tsConfig ?? (0, js_1.getRootTsConfigPath)();
203
225
  const plugins = [];
204
226
  const isUsingTsSolution = (0, internal_1.isUsingTsSolutionSetup)();
@@ -235,8 +257,7 @@ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
235
257
  typeCheckOptions = defaultTypeCheckOptions;
236
258
  }
237
259
  // New TS Solution already has a typecheck target but allow it to run during serve
238
- const shouldTypeCheck = typeCheckOptions !== false &&
239
- (!isUsingTsSolution || process.env['WEBPACK_SERVE']);
260
+ const shouldTypeCheck = typeCheckOptions !== false && (!isUsingTsSolution || (0, is_serve_mode_1.isServeMode)());
240
261
  if (shouldTypeCheck) {
241
262
  const { TsCheckerRspackPlugin } = require('ts-checker-rspack-plugin');
242
263
  const pluginConfig = {
@@ -292,7 +313,7 @@ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
292
313
  }
293
314
  });
294
315
  if (options.progress) {
295
- plugins.push(new core_1.ProgressPlugin({ profile: options.verbose }));
316
+ plugins.push(new ProgressPlugin({ profile: options.verbose }));
296
317
  }
297
318
  if (options.extractLicenses) {
298
319
  plugins.push(new license_webpack_plugin_1.LicenseWebpackPlugin({
@@ -305,7 +326,7 @@ function applyNxDependentConfig(options, config, { useNormalizedEntry } = {}) {
305
326
  }));
306
327
  }
307
328
  if (Array.isArray(options.assets) && options.assets.length > 0) {
308
- plugins.push(new core_1.CopyRspackPlugin({
329
+ plugins.push(new CopyRspackPlugin({
309
330
  patterns: options.assets.map((asset) => {
310
331
  return {
311
332
  context: asset.input,
@@ -1,2 +1,13 @@
1
- import { Configuration, RspackOptionsNormalized } from '@rspack/core';
2
- export declare function applyReactConfig(options?: Record<string, any>, config?: Partial<RspackOptionsNormalized | Configuration>): void;
1
+ import type { Compiler, Configuration, RspackOptionsNormalized } from '@rspack/core';
2
+ type RspackConfigShape = Partial<RspackOptionsNormalized | Configuration>;
3
+ /**
4
+ * Apply rspack/react config for the compose path (e.g. `withReact`):
5
+ * sync tweaks + push react-refresh into `config.plugins`. Plugins that
6
+ * participate in rspack's lifecycle should call
7
+ * `applyReactConfigSync(...)` + `applyReactHotReloadToCompiler(...)`
8
+ * instead.
9
+ */
10
+ export declare function applyReactConfig(options?: Record<string, any>, config?: RspackConfigShape): void;
11
+ export declare function applyReactConfigSync(config: RspackConfigShape): void;
12
+ export declare function applyReactHotReloadToCompiler(compiler: Compiler): void;
13
+ export {};