@nx/rsbuild 23.0.0 → 23.1.0-beta.0
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.
- package/README.md +1 -2
- package/dist/src/generators/configuration/configuration.js +24 -0
- package/dist/src/generators/configuration/files/rsbuild.config.ts__tpl__ +6 -1
- package/dist/src/migrations/update-23-0-0/migrate-node-output-to-esm.md +92 -0
- package/dist/src/migrations/update-23-0-0/migrate-performance-options.md +182 -0
- package/dist/src/migrations/update-23-0-0/migrate-rsbuild-config-to-v2.d.ts +86 -0
- package/dist/src/migrations/update-23-0-0/migrate-rsbuild-config-to-v2.js +370 -0
- package/dist/src/plugins/plugin.js +3 -1
- package/dist/src/utils/versions.d.ts +1 -1
- package/dist/src/utils/versions.js +17 -9
- package/migrations.json +45 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -7,13 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
<div style="text-align: center;">
|
|
9
9
|
|
|
10
|
-
[](https://circleci.com/gh/nrwl/nx)
|
|
11
10
|
[]()
|
|
12
11
|
[](https://www.npmjs.com/package/nx)
|
|
13
12
|
[]()
|
|
14
13
|
[](http://commitizen.github.io/cz-cli/)
|
|
15
|
-
[](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
16
14
|
[](https://go.nx.dev/community)
|
|
15
|
+
[](https://nx.dev/docs/features/ci-features/sandboxing)
|
|
17
16
|
|
|
18
17
|
</div>
|
|
19
18
|
|
|
@@ -43,10 +43,34 @@ async function configurationGenerator(tree, schema) {
|
|
|
43
43
|
}
|
|
44
44
|
const rsbuildVersions = (0, version_utils_1.getRsbuildVersionsForInstalledMajor)(tree);
|
|
45
45
|
tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@rsbuild/core': rsbuildVersions.rsbuildVersion }, undefined, true));
|
|
46
|
+
// @rsbuild/core@2 emits ESM output by default for both web and Node
|
|
47
|
+
// targets. There are two ways to make that output runnable:
|
|
48
|
+
// 1. `"type": "module"` on the project package.json — rsbuild's own
|
|
49
|
+
// `create-rsbuild` convention. Used when the project owns a
|
|
50
|
+
// package.json (fabricating one, or landing `type` on the
|
|
51
|
+
// workspace root, would flip every .js file in the repo to ESM).
|
|
52
|
+
// 2. `.mjs` output filenames — used for Node builds when the
|
|
53
|
+
// project has no package.json to carry `"type": "module"`.
|
|
54
|
+
// `.mjs` is unconditionally ESM regardless of the nearest
|
|
55
|
+
// package.json. Web output doesn't need this; the browser loads
|
|
56
|
+
// it via `<script type="module">`.
|
|
57
|
+
// Both are v2-only — on v1 rsbuild still emits CommonJS.
|
|
58
|
+
const installedRsbuildMajor = (0, version_utils_1.getInstalledRsbuildMajorVersion)(tree);
|
|
59
|
+
const isV2 = installedRsbuildMajor === undefined || installedRsbuildMajor >= 2;
|
|
60
|
+
const projectPackageJsonPath = (0, path_1.join)(options.projectRoot, 'package.json');
|
|
61
|
+
const projectHasPackageJson = tree.exists(projectPackageJsonPath);
|
|
62
|
+
const useMjsOutput = isV2 && options.target === 'node' && !projectHasPackageJson;
|
|
46
63
|
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), options.projectRoot, {
|
|
47
64
|
...options,
|
|
65
|
+
useMjsOutput,
|
|
48
66
|
tpl: '',
|
|
49
67
|
});
|
|
68
|
+
if (isV2 && projectHasPackageJson) {
|
|
69
|
+
(0, devkit_1.updateJson)(tree, projectPackageJsonPath, (json) => {
|
|
70
|
+
json.type ??= 'module';
|
|
71
|
+
return json;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
50
74
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
51
75
|
}
|
|
52
76
|
exports.default = configurationGenerator;
|
|
@@ -11,7 +11,12 @@ export default defineConfig({
|
|
|
11
11
|
port: <%= devServerPort %>
|
|
12
12
|
},
|
|
13
13
|
output: {
|
|
14
|
-
target: '<%= target %>'
|
|
14
|
+
target: '<%= target %>',<% if (useMjsOutput) { %>
|
|
15
|
+
// @rsbuild/core@2 emits ESM for Node targets. Emit .mjs so the
|
|
16
|
+
// output runs without a `"type": "module"` package.json.
|
|
17
|
+
filename: {
|
|
18
|
+
js: '[name].mjs',
|
|
19
|
+
},<% } %>
|
|
15
20
|
distPath: {
|
|
16
21
|
root: 'dist',
|
|
17
22
|
},
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#### Make Node-target rsbuild builds runnable under `@rsbuild/core@2`
|
|
2
|
+
|
|
3
|
+
`@rsbuild/core@2` changed the default output format for Node targets. In v1,
|
|
4
|
+
`output.target: 'node'` produced **minified CommonJS**. In v2 it produces
|
|
5
|
+
**unminified ESM** (`output.module` defaults to `true`, `output.minify` to
|
|
6
|
+
`false`).
|
|
7
|
+
|
|
8
|
+
A v2 ESM bundle does not run as plain `node dist/index.js` unless one of the
|
|
9
|
+
following is true:
|
|
10
|
+
|
|
11
|
+
- a `package.json` with `"type": "module"` governs the output, **or**
|
|
12
|
+
- the output files use the `.mjs` extension.
|
|
13
|
+
|
|
14
|
+
Without one of those, the build succeeds but the process crashes at runtime
|
|
15
|
+
with `Cannot use import statement outside a module`.
|
|
16
|
+
|
|
17
|
+
This is workspace-specific — it depends on whether the project owns a
|
|
18
|
+
`package.json`, what runs or references the bundle (a `main` field, a
|
|
19
|
+
Dockerfile, a deploy script, a `serve` target), and whether other `.js`
|
|
20
|
+
files in the project are CommonJS. So it ships as an AI-assisted
|
|
21
|
+
instruction rather than a blind codemod.
|
|
22
|
+
|
|
23
|
+
#### What needs to change
|
|
24
|
+
|
|
25
|
+
For every project with an `rsbuild.config.{ts,js,mjs,cjs}` whose
|
|
26
|
+
`output.target` is `'node'`:
|
|
27
|
+
|
|
28
|
+
1. **Decide how the ESM output should be made runnable.** Prefer, in order:
|
|
29
|
+
- **The project owns its own `package.json`** → set `"type": "module"`
|
|
30
|
+
on it. This is rsbuild's recommended convention. Check first that no
|
|
31
|
+
sibling `.js` files in the project rely on CommonJS (`require`,
|
|
32
|
+
`module.exports`, `__dirname`); if any do, rename them to `.cjs` or
|
|
33
|
+
convert them to ESM.
|
|
34
|
+
|
|
35
|
+
- **The project has no `package.json`** → add `.mjs` output to the
|
|
36
|
+
rsbuild config instead, so the output is ESM regardless of any
|
|
37
|
+
ancestor `package.json`:
|
|
38
|
+
|
|
39
|
+
```ts title="rsbuild.config.ts"
|
|
40
|
+
export default defineConfig({
|
|
41
|
+
output: {
|
|
42
|
+
target: 'node',
|
|
43
|
+
filename: { js: '[name].mjs' },
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
2. **Update anything that references the output filename.** If you chose
|
|
49
|
+
`.mjs`, fix references in `package.json#main`, Dockerfiles, `serve`
|
|
50
|
+
targets, deploy scripts, and any `import`/`require` of the built file.
|
|
51
|
+
|
|
52
|
+
3. **Do not pin back to CommonJS** unless the project genuinely cannot move
|
|
53
|
+
to ESM. If you must, restore the v1 behavior explicitly:
|
|
54
|
+
|
|
55
|
+
```ts title="rsbuild.config.ts"
|
|
56
|
+
export default defineConfig({
|
|
57
|
+
output: {
|
|
58
|
+
target: 'node',
|
|
59
|
+
module: false,
|
|
60
|
+
minify: true,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### Sample Code Changes
|
|
66
|
+
|
|
67
|
+
##### Before — Node project, no project package.json
|
|
68
|
+
|
|
69
|
+
```ts title="apps/api/rsbuild.config.ts" {4}
|
|
70
|
+
export default defineConfig({
|
|
71
|
+
output: {
|
|
72
|
+
target: 'node',
|
|
73
|
+
distPath: { root: 'dist' },
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
##### After — `.mjs` output so the ESM bundle runs
|
|
79
|
+
|
|
80
|
+
```ts title="apps/api/rsbuild.config.ts" {4}
|
|
81
|
+
export default defineConfig({
|
|
82
|
+
output: {
|
|
83
|
+
target: 'node',
|
|
84
|
+
filename: { js: '[name].mjs' },
|
|
85
|
+
distPath: { root: 'dist' },
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Reference
|
|
91
|
+
|
|
92
|
+
[`@rsbuild/core` v1 → v2 upgrade guide — Node output](https://rsbuild.rs/guide/upgrade/v1-to-v2#node-output)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#### Migrate `performance` options for `@rsbuild/core@2`
|
|
2
|
+
|
|
3
|
+
`@rsbuild/core@2` removed two `performance` options and deprecated a third.
|
|
4
|
+
rsbuild v2 does not hard-error on the stale keys — it warns and ignores the
|
|
5
|
+
removed ones, and the deprecated one still works — so the changes here are
|
|
6
|
+
about adopting the replacements rather than fixing a broken build. None
|
|
7
|
+
have a drop-in key rename, so this ships as an AI-assisted instruction.
|
|
8
|
+
|
|
9
|
+
This only affects projects whose `rsbuild.config.{ts,js,mjs,cjs}` sets one
|
|
10
|
+
of the options below. If none of your configs use them, there is nothing
|
|
11
|
+
to do.
|
|
12
|
+
|
|
13
|
+
#### `performance.bundleAnalyze` was removed
|
|
14
|
+
|
|
15
|
+
rsbuild v1 bundled `webpack-bundle-analyzer` and exposed it through
|
|
16
|
+
`performance.bundleAnalyze`. v2 removed it to cut install size.
|
|
17
|
+
|
|
18
|
+
For every config that sets `performance.bundleAnalyze`, remove that option
|
|
19
|
+
and pick one replacement:
|
|
20
|
+
|
|
21
|
+
- **Preferred — Rsdoctor.** Add the [Rsdoctor](https://rsdoctor.dev) plugin;
|
|
22
|
+
it covers bundle-size analysis and more. See
|
|
23
|
+
[rsbuild.rs/guide/debug/rsdoctor](https://rsbuild.rs/guide/debug/rsdoctor).
|
|
24
|
+
|
|
25
|
+
- **Keep webpack-bundle-analyzer.** Install it and register it via
|
|
26
|
+
`tools.rspack`:
|
|
27
|
+
|
|
28
|
+
```ts title="rsbuild.config.ts"
|
|
29
|
+
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
tools: {
|
|
33
|
+
rspack: {
|
|
34
|
+
plugins: [new BundleAnalyzerPlugin({ analyzerMode: 'static' })],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If `performance` is left empty after removing the option, delete the empty
|
|
41
|
+
`performance: {}` block too.
|
|
42
|
+
|
|
43
|
+
#### `performance.profile` was removed
|
|
44
|
+
|
|
45
|
+
`performance.profile` emitted an rspack stats JSON file. v2 removed it; emit
|
|
46
|
+
the file from a small custom plugin instead.
|
|
47
|
+
|
|
48
|
+
For every config that sets `performance.profile: true`, remove that option
|
|
49
|
+
and add:
|
|
50
|
+
|
|
51
|
+
```ts title="rsbuild.config.ts"
|
|
52
|
+
import { writeFileSync } from 'node:fs';
|
|
53
|
+
import { join } from 'node:path';
|
|
54
|
+
|
|
55
|
+
const statsJsonPlugin = {
|
|
56
|
+
name: 'stats-json-plugin',
|
|
57
|
+
setup(api) {
|
|
58
|
+
api.onAfterBuild(({ stats }) => {
|
|
59
|
+
writeFileSync(
|
|
60
|
+
join(api.context.distPath, 'stats.json'),
|
|
61
|
+
JSON.stringify(stats?.toJson({}), null, 2)
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default {
|
|
68
|
+
plugins: [statsJsonPlugin],
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### `performance.chunkSplit` is deprecated
|
|
73
|
+
|
|
74
|
+
`performance.chunkSplit` still works in v2 but is deprecated. Migrate it to
|
|
75
|
+
the new top-level `splitChunks` option, which aligns with Rspack's
|
|
76
|
+
`optimization.splitChunks`.
|
|
77
|
+
|
|
78
|
+
For every config that sets `performance.chunkSplit`, translate `strategy`:
|
|
79
|
+
|
|
80
|
+
| `chunkSplit.strategy` | `splitChunks` replacement |
|
|
81
|
+
| -------------------------------------------- | ----------------------------------------------- |
|
|
82
|
+
| `split-by-experience` | `{ preset: 'default' }` |
|
|
83
|
+
| `split-by-module` | `{ preset: 'per-package' }` |
|
|
84
|
+
| `single-vendor` | `{ preset: 'single-vendor' }` |
|
|
85
|
+
| `all-in-one` | `false` (chunk splitting disabled) |
|
|
86
|
+
| `custom` (with a nested `splitChunks`) | `{ preset: 'none', ...the nested splitChunks }` |
|
|
87
|
+
| `split-by-size` (with `minSize` / `maxSize`) | `{ preset: 'none', minSize, maxSize }` |
|
|
88
|
+
|
|
89
|
+
Then translate the remaining `chunkSplit` keys:
|
|
90
|
+
|
|
91
|
+
- `override` → spread its contents directly into the top-level `splitChunks`.
|
|
92
|
+
- `forceSplitting` → `splitChunks.cacheGroups`. Each `forceSplitting` entry
|
|
93
|
+
`name: <RegExp>` expands to a full cache group:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
cacheGroups: {
|
|
97
|
+
<name>: {
|
|
98
|
+
test: <RegExp>,
|
|
99
|
+
name: '<name>',
|
|
100
|
+
chunks: 'all',
|
|
101
|
+
// priority 0 normally; use 1 when the `single-vendor` preset is set
|
|
102
|
+
priority: 0,
|
|
103
|
+
enforce: true,
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
##### `forceSplitting` example
|
|
109
|
+
|
|
110
|
+
```diff title="rsbuild.config.ts"
|
|
111
|
+
export default {
|
|
112
|
+
- performance: {
|
|
113
|
+
- chunkSplit: {
|
|
114
|
+
- forceSplitting: {
|
|
115
|
+
- axios: /node_modules[\\/]axios/,
|
|
116
|
+
- },
|
|
117
|
+
- },
|
|
118
|
+
- },
|
|
119
|
+
+ splitChunks: {
|
|
120
|
+
+ cacheGroups: {
|
|
121
|
+
+ axios: {
|
|
122
|
+
+ test: /node_modules[\\/]axios/,
|
|
123
|
+
+ name: 'axios',
|
|
124
|
+
+ chunks: 'all',
|
|
125
|
+
+ priority: 0,
|
|
126
|
+
+ enforce: true,
|
|
127
|
+
+ },
|
|
128
|
+
+ },
|
|
129
|
+
+ },
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
If `performance` is empty after removing `chunkSplit`, delete the empty
|
|
134
|
+
`performance: {}` block.
|
|
135
|
+
|
|
136
|
+
#### Sample Code Changes
|
|
137
|
+
|
|
138
|
+
##### Before
|
|
139
|
+
|
|
140
|
+
```ts title="apps/web/rsbuild.config.ts" {3-5}
|
|
141
|
+
export default defineConfig({
|
|
142
|
+
performance: {
|
|
143
|
+
bundleAnalyze: {},
|
|
144
|
+
profile: true,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
##### After
|
|
150
|
+
|
|
151
|
+
```ts title="apps/web/rsbuild.config.ts"
|
|
152
|
+
import { writeFileSync } from 'node:fs';
|
|
153
|
+
import { join } from 'node:path';
|
|
154
|
+
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
|
155
|
+
|
|
156
|
+
const statsJsonPlugin = {
|
|
157
|
+
name: 'stats-json-plugin',
|
|
158
|
+
setup(api) {
|
|
159
|
+
api.onAfterBuild(({ stats }) => {
|
|
160
|
+
writeFileSync(
|
|
161
|
+
join(api.context.distPath, 'stats.json'),
|
|
162
|
+
JSON.stringify(stats?.toJson({}), null, 2)
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export default defineConfig({
|
|
169
|
+
plugins: [statsJsonPlugin],
|
|
170
|
+
tools: {
|
|
171
|
+
rspack: {
|
|
172
|
+
plugins: [new BundleAnalyzerPlugin({ analyzerMode: 'static' })],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### Reference
|
|
179
|
+
|
|
180
|
+
- [`@rsbuild/core` v1 → v2 upgrade guide — Remove `performance.bundleAnalyze`](https://rsbuild.rs/guide/upgrade/v1-to-v2#remove-performancebundleanalyze)
|
|
181
|
+
- [`@rsbuild/core` v1 → v2 upgrade guide — Remove `performance.profile`](https://rsbuild.rs/guide/upgrade/v1-to-v2#remove-performanceprofile)
|
|
182
|
+
- [`@rsbuild/core` v1 → v2 upgrade guide — Migrate `performance.chunkSplit`](https://rsbuild.rs/guide/upgrade/v1-to-v2#migrate-performancechunksplit)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type Tree } from '@nx/devkit';
|
|
2
|
+
/**
|
|
3
|
+
* Rewrite user-authored `rsbuild.config.{js,ts,mjs,cjs}` files for
|
|
4
|
+
* @rsbuild/core@2 compatibility. Five transformations:
|
|
5
|
+
*
|
|
6
|
+
* 1. `preview.setupMiddlewares` → `server.setupMiddlewares`. v2 moved
|
|
7
|
+
* middleware setup off the preview-only namespace.
|
|
8
|
+
*
|
|
9
|
+
* 2. `performance.removeMomentLocale: true|false` is dropped — v2
|
|
10
|
+
* removed the option entirely. moment locale stripping in v2 is
|
|
11
|
+
* handled via standard externals/aliases.
|
|
12
|
+
*
|
|
13
|
+
* 3. `source.alias` / `source.aliasStrategy` → `resolve.alias` /
|
|
14
|
+
* `resolve.aliasStrategy`. v2 removed the deprecated `source`-level
|
|
15
|
+
* options in favor of the `resolve` block.
|
|
16
|
+
*
|
|
17
|
+
* 4. `server.proxy` entry `context` → `pathFilter`. v2's
|
|
18
|
+
* http-proxy-middleware@4 renamed the matcher option.
|
|
19
|
+
*
|
|
20
|
+
* 5. `server.proxy` entry `on{Open,Close,Error,ProxyReq,ProxyRes}`
|
|
21
|
+
* handlers → a unified `on: { open, close, error, proxyReq,
|
|
22
|
+
* proxyRes }` object.
|
|
23
|
+
*
|
|
24
|
+
* Other v2 changes (default `host` flip from 0.0.0.0 to localhost,
|
|
25
|
+
* default `loadConfig: 'auto'`, Node target ESM default) are behavior
|
|
26
|
+
* changes that don't have a deterministic config-rewrite recipe — they
|
|
27
|
+
* live in the docs / release notes instead.
|
|
28
|
+
*
|
|
29
|
+
* All transforms are AST-based: walk the TypeScript parse tree and
|
|
30
|
+
* patch source ranges so quoted keys, spreads, and surrounding comments
|
|
31
|
+
* are preserved.
|
|
32
|
+
*/
|
|
33
|
+
export default function migrateRsbuildConfigToV2(tree: Tree): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Exported for unit testing. Rewrites a single-key
|
|
36
|
+
* `preview: { setupMiddlewares: [...] }` literal to
|
|
37
|
+
* `server: { setupMiddlewares: [...] }`.
|
|
38
|
+
*
|
|
39
|
+
* Narrowed to the single-key shape only. For any other shape — preview
|
|
40
|
+
* with host/port/headers, multiple keys, or anything beyond the
|
|
41
|
+
* setupMiddlewares array — the file is left untouched. A blanket
|
|
42
|
+
* rename would move options that still belong under `preview` in v2,
|
|
43
|
+
* or duplicate a `server:` key the user already has elsewhere.
|
|
44
|
+
*/
|
|
45
|
+
export declare function renameSetupMiddlewares(source: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Exported for unit testing. Drops `removeMomentLocale: true|false`
|
|
48
|
+
* property assignments anywhere in the config — v2 removed the option,
|
|
49
|
+
* so the value is irrelevant.
|
|
50
|
+
*/
|
|
51
|
+
export declare function dropRemoveMomentLocale(source: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Exported for unit testing. Relocates `source.alias` and
|
|
54
|
+
* `source.aliasStrategy` into a sibling `resolve` block — v2 removed
|
|
55
|
+
* the deprecated `source`-level forms.
|
|
56
|
+
*
|
|
57
|
+
* Three shapes are handled per config object:
|
|
58
|
+
* - `source` has only the alias keys, no `resolve` → rename the
|
|
59
|
+
* `source` key to `resolve` (one-token edit).
|
|
60
|
+
* - `source` has alias keys plus others, with an existing `resolve`
|
|
61
|
+
* block → splice the alias properties into the `resolve` block.
|
|
62
|
+
* - same, but no `resolve` block → create one immediately before
|
|
63
|
+
* `source` carrying the alias properties.
|
|
64
|
+
*
|
|
65
|
+
* `formatFiles` tidies whitespace afterward, so the inserts only need
|
|
66
|
+
* to be syntactically valid, not pretty.
|
|
67
|
+
*/
|
|
68
|
+
export declare function moveSourceAliasToResolve(source: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Exported for unit testing. Renames the `context` matcher option to
|
|
71
|
+
* `pathFilter` inside `server.proxy` entries — http-proxy-middleware@4
|
|
72
|
+
* (pulled in by @rsbuild/core@2) renamed it. Anchored to a proxy entry
|
|
73
|
+
* so an unrelated `context` key elsewhere is left alone.
|
|
74
|
+
*/
|
|
75
|
+
export declare function renameProxyContext(source: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Exported for unit testing. Consolidates the per-event proxy handlers
|
|
78
|
+
* (`onOpen`, `onClose`, `onError`, `onProxyReq`, `onProxyRes`) into a
|
|
79
|
+
* single `on: { open, close, error, proxyReq, proxyRes }` object —
|
|
80
|
+
* http-proxy-middleware@4's unified event API.
|
|
81
|
+
*
|
|
82
|
+
* Skips any proxy entry that already has an `on` property (already
|
|
83
|
+
* migrated). Anchored to proxy entries so unrelated `on*` keys are
|
|
84
|
+
* untouched.
|
|
85
|
+
*/
|
|
86
|
+
export declare function groupProxyEventHandlers(source: string): string;
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = migrateRsbuildConfigToV2;
|
|
4
|
+
exports.renameSetupMiddlewares = renameSetupMiddlewares;
|
|
5
|
+
exports.dropRemoveMomentLocale = dropRemoveMomentLocale;
|
|
6
|
+
exports.moveSourceAliasToResolve = moveSourceAliasToResolve;
|
|
7
|
+
exports.renameProxyContext = renameProxyContext;
|
|
8
|
+
exports.groupProxyEventHandlers = groupProxyEventHandlers;
|
|
9
|
+
const tslib_1 = require("tslib");
|
|
10
|
+
const devkit_1 = require("@nx/devkit");
|
|
11
|
+
const tsquery_1 = require("@phenomnomnominal/tsquery");
|
|
12
|
+
const ts = tslib_1.__importStar(require("typescript"));
|
|
13
|
+
/**
|
|
14
|
+
* Rewrite user-authored `rsbuild.config.{js,ts,mjs,cjs}` files for
|
|
15
|
+
* @rsbuild/core@2 compatibility. Five transformations:
|
|
16
|
+
*
|
|
17
|
+
* 1. `preview.setupMiddlewares` → `server.setupMiddlewares`. v2 moved
|
|
18
|
+
* middleware setup off the preview-only namespace.
|
|
19
|
+
*
|
|
20
|
+
* 2. `performance.removeMomentLocale: true|false` is dropped — v2
|
|
21
|
+
* removed the option entirely. moment locale stripping in v2 is
|
|
22
|
+
* handled via standard externals/aliases.
|
|
23
|
+
*
|
|
24
|
+
* 3. `source.alias` / `source.aliasStrategy` → `resolve.alias` /
|
|
25
|
+
* `resolve.aliasStrategy`. v2 removed the deprecated `source`-level
|
|
26
|
+
* options in favor of the `resolve` block.
|
|
27
|
+
*
|
|
28
|
+
* 4. `server.proxy` entry `context` → `pathFilter`. v2's
|
|
29
|
+
* http-proxy-middleware@4 renamed the matcher option.
|
|
30
|
+
*
|
|
31
|
+
* 5. `server.proxy` entry `on{Open,Close,Error,ProxyReq,ProxyRes}`
|
|
32
|
+
* handlers → a unified `on: { open, close, error, proxyReq,
|
|
33
|
+
* proxyRes }` object.
|
|
34
|
+
*
|
|
35
|
+
* Other v2 changes (default `host` flip from 0.0.0.0 to localhost,
|
|
36
|
+
* default `loadConfig: 'auto'`, Node target ESM default) are behavior
|
|
37
|
+
* changes that don't have a deterministic config-rewrite recipe — they
|
|
38
|
+
* live in the docs / release notes instead.
|
|
39
|
+
*
|
|
40
|
+
* All transforms are AST-based: walk the TypeScript parse tree and
|
|
41
|
+
* patch source ranges so quoted keys, spreads, and surrounding comments
|
|
42
|
+
* are preserved.
|
|
43
|
+
*/
|
|
44
|
+
async function migrateRsbuildConfigToV2(tree) {
|
|
45
|
+
const configFiles = [];
|
|
46
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
|
|
47
|
+
if (filePath.endsWith('rsbuild.config.ts') ||
|
|
48
|
+
filePath.endsWith('rsbuild.config.js') ||
|
|
49
|
+
filePath.endsWith('rsbuild.config.mjs') ||
|
|
50
|
+
filePath.endsWith('rsbuild.config.cjs')) {
|
|
51
|
+
configFiles.push(filePath);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
for (const configFile of configFiles) {
|
|
55
|
+
const original = tree.read(configFile, 'utf-8');
|
|
56
|
+
if (!original)
|
|
57
|
+
continue;
|
|
58
|
+
let next = renameSetupMiddlewares(original);
|
|
59
|
+
next = dropRemoveMomentLocale(next);
|
|
60
|
+
next = moveSourceAliasToResolve(next);
|
|
61
|
+
next = renameProxyContext(next);
|
|
62
|
+
next = groupProxyEventHandlers(next);
|
|
63
|
+
if (next !== original) {
|
|
64
|
+
tree.write(configFile, next);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
68
|
+
}
|
|
69
|
+
function applyEdits(source, edits) {
|
|
70
|
+
if (edits.length === 0)
|
|
71
|
+
return source;
|
|
72
|
+
const sorted = [...edits].sort((a, b) => b.start - a.start);
|
|
73
|
+
return sorted.reduce((acc, e) => acc.slice(0, e.start) + e.replacement + acc.slice(e.end), source);
|
|
74
|
+
}
|
|
75
|
+
function getPropertyName(prop) {
|
|
76
|
+
const name = prop.name;
|
|
77
|
+
if (ts.isIdentifier(name))
|
|
78
|
+
return name.text;
|
|
79
|
+
if (ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name)) {
|
|
80
|
+
return name.text;
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Exported for unit testing. Rewrites a single-key
|
|
86
|
+
* `preview: { setupMiddlewares: [...] }` literal to
|
|
87
|
+
* `server: { setupMiddlewares: [...] }`.
|
|
88
|
+
*
|
|
89
|
+
* Narrowed to the single-key shape only. For any other shape — preview
|
|
90
|
+
* with host/port/headers, multiple keys, or anything beyond the
|
|
91
|
+
* setupMiddlewares array — the file is left untouched. A blanket
|
|
92
|
+
* rename would move options that still belong under `preview` in v2,
|
|
93
|
+
* or duplicate a `server:` key the user already has elsewhere.
|
|
94
|
+
*/
|
|
95
|
+
function renameSetupMiddlewares(source) {
|
|
96
|
+
if (!source.includes('setupMiddlewares'))
|
|
97
|
+
return source;
|
|
98
|
+
const sourceFile = (0, tsquery_1.ast)(source);
|
|
99
|
+
const edits = [];
|
|
100
|
+
const visit = (node) => {
|
|
101
|
+
if (ts.isPropertyAssignment(node) &&
|
|
102
|
+
getPropertyName(node) === 'preview' &&
|
|
103
|
+
ts.isObjectLiteralExpression(node.initializer)) {
|
|
104
|
+
const props = node.initializer.properties;
|
|
105
|
+
if (props.length === 1 &&
|
|
106
|
+
ts.isPropertyAssignment(props[0]) &&
|
|
107
|
+
getPropertyName(props[0]) === 'setupMiddlewares') {
|
|
108
|
+
// Replace only the property name `preview` → `server`. The
|
|
109
|
+
// initializer (the object literal with setupMiddlewares) stays
|
|
110
|
+
// untouched, preserving its formatting verbatim.
|
|
111
|
+
const nameNode = node.name;
|
|
112
|
+
edits.push({
|
|
113
|
+
start: nameNode.getStart(sourceFile),
|
|
114
|
+
end: nameNode.getEnd(),
|
|
115
|
+
replacement: 'server',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
ts.forEachChild(node, visit);
|
|
120
|
+
};
|
|
121
|
+
visit(sourceFile);
|
|
122
|
+
return applyEdits(source, edits);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Exported for unit testing. Drops `removeMomentLocale: true|false`
|
|
126
|
+
* property assignments anywhere in the config — v2 removed the option,
|
|
127
|
+
* so the value is irrelevant.
|
|
128
|
+
*/
|
|
129
|
+
function dropRemoveMomentLocale(source) {
|
|
130
|
+
if (!source.includes('removeMomentLocale'))
|
|
131
|
+
return source;
|
|
132
|
+
const sourceFile = (0, tsquery_1.ast)(source);
|
|
133
|
+
const edits = [];
|
|
134
|
+
const visit = (node) => {
|
|
135
|
+
if (ts.isPropertyAssignment(node) &&
|
|
136
|
+
getPropertyName(node) === 'removeMomentLocale' &&
|
|
137
|
+
(node.initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
138
|
+
node.initializer.kind === ts.SyntaxKind.FalseKeyword)) {
|
|
139
|
+
let endOfRemoval = node.getEnd();
|
|
140
|
+
const trailingText = source.slice(endOfRemoval);
|
|
141
|
+
const trailingMatch = trailingText.match(/^\s*,?\s*\r?\n/);
|
|
142
|
+
if (trailingMatch) {
|
|
143
|
+
endOfRemoval += trailingMatch[0].length;
|
|
144
|
+
}
|
|
145
|
+
let startOfRemoval = node.getStart(sourceFile);
|
|
146
|
+
const lineStart = source.lastIndexOf('\n', startOfRemoval - 1) + 1;
|
|
147
|
+
if (source.slice(lineStart, startOfRemoval).trim() === '') {
|
|
148
|
+
startOfRemoval = lineStart;
|
|
149
|
+
}
|
|
150
|
+
edits.push({
|
|
151
|
+
start: startOfRemoval,
|
|
152
|
+
end: endOfRemoval,
|
|
153
|
+
replacement: '',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
ts.forEachChild(node, visit);
|
|
157
|
+
};
|
|
158
|
+
visit(sourceFile);
|
|
159
|
+
return applyEdits(source, edits);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Exported for unit testing. Relocates `source.alias` and
|
|
163
|
+
* `source.aliasStrategy` into a sibling `resolve` block — v2 removed
|
|
164
|
+
* the deprecated `source`-level forms.
|
|
165
|
+
*
|
|
166
|
+
* Three shapes are handled per config object:
|
|
167
|
+
* - `source` has only the alias keys, no `resolve` → rename the
|
|
168
|
+
* `source` key to `resolve` (one-token edit).
|
|
169
|
+
* - `source` has alias keys plus others, with an existing `resolve`
|
|
170
|
+
* block → splice the alias properties into the `resolve` block.
|
|
171
|
+
* - same, but no `resolve` block → create one immediately before
|
|
172
|
+
* `source` carrying the alias properties.
|
|
173
|
+
*
|
|
174
|
+
* `formatFiles` tidies whitespace afterward, so the inserts only need
|
|
175
|
+
* to be syntactically valid, not pretty.
|
|
176
|
+
*/
|
|
177
|
+
function moveSourceAliasToResolve(source) {
|
|
178
|
+
if (!/\balias(?:Strategy)?\b/.test(source))
|
|
179
|
+
return source;
|
|
180
|
+
const sourceFile = (0, tsquery_1.ast)(source);
|
|
181
|
+
const edits = [];
|
|
182
|
+
const ALIAS_KEYS = new Set(['alias', 'aliasStrategy']);
|
|
183
|
+
const visit = (node) => {
|
|
184
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
185
|
+
const sourceProp = node.properties.find((p) => ts.isPropertyAssignment(p) && getPropertyName(p) === 'source');
|
|
186
|
+
if (sourceProp && ts.isObjectLiteralExpression(sourceProp.initializer)) {
|
|
187
|
+
const sourceObj = sourceProp.initializer;
|
|
188
|
+
const aliasProps = sourceObj.properties.filter((p) => ts.isPropertyAssignment(p) &&
|
|
189
|
+
ALIAS_KEYS.has(getPropertyName(p) ?? ''));
|
|
190
|
+
if (aliasProps.length > 0) {
|
|
191
|
+
const resolveProp = node.properties.find((p) => ts.isPropertyAssignment(p) && getPropertyName(p) === 'resolve');
|
|
192
|
+
const aliasAreAllProps = aliasProps.length === sourceObj.properties.length;
|
|
193
|
+
if (!resolveProp && aliasAreAllProps) {
|
|
194
|
+
// `source` carries nothing but the alias keys — just rename
|
|
195
|
+
// the property to `resolve`.
|
|
196
|
+
edits.push({
|
|
197
|
+
start: sourceProp.name.getStart(sourceFile),
|
|
198
|
+
end: sourceProp.name.getEnd(),
|
|
199
|
+
replacement: 'resolve',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const movedTexts = aliasProps.map((p) => p.getText(sourceFile));
|
|
204
|
+
// Remove each alias property from `source` (+ trailing
|
|
205
|
+
// comma / line terminator).
|
|
206
|
+
for (const p of aliasProps) {
|
|
207
|
+
let end = p.getEnd();
|
|
208
|
+
const trailing = source.slice(end).match(/^\s*,?\s*\r?\n?/);
|
|
209
|
+
if (trailing)
|
|
210
|
+
end += trailing[0].length;
|
|
211
|
+
let start = p.getStart(sourceFile);
|
|
212
|
+
const lineStart = source.lastIndexOf('\n', start - 1) + 1;
|
|
213
|
+
if (source.slice(lineStart, start).trim() === '') {
|
|
214
|
+
start = lineStart;
|
|
215
|
+
}
|
|
216
|
+
edits.push({ start, end, replacement: '' });
|
|
217
|
+
}
|
|
218
|
+
if (resolveProp &&
|
|
219
|
+
ts.isObjectLiteralExpression(resolveProp.initializer)) {
|
|
220
|
+
// Splice into the existing `resolve` block, just before
|
|
221
|
+
// its closing brace. Lead with a comma when the block
|
|
222
|
+
// already has properties so we don't fuse onto a
|
|
223
|
+
// comma-less last property.
|
|
224
|
+
const closeBrace = resolveProp.initializer.getEnd() - 1;
|
|
225
|
+
const leadingSep = resolveProp.initializer.properties.length > 0 ? ',\n' : '';
|
|
226
|
+
edits.push({
|
|
227
|
+
start: closeBrace,
|
|
228
|
+
end: closeBrace,
|
|
229
|
+
replacement: leadingSep + movedTexts.map((t) => `${t},\n`).join(''),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
// No `resolve` block — create one right before `source`.
|
|
234
|
+
const insertAt = sourceProp.getStart(sourceFile);
|
|
235
|
+
edits.push({
|
|
236
|
+
start: insertAt,
|
|
237
|
+
end: insertAt,
|
|
238
|
+
replacement: `resolve: {\n${movedTexts
|
|
239
|
+
.map((t) => `${t},\n`)
|
|
240
|
+
.join('')}},\n`,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
ts.forEachChild(node, visit);
|
|
248
|
+
};
|
|
249
|
+
visit(sourceFile);
|
|
250
|
+
return applyEdits(source, edits);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Returns true when `obj` is a `server.proxy` entry — either an element
|
|
254
|
+
* of the array form (`proxy: [{ ... }]`) or a value of the object-map
|
|
255
|
+
* form (`proxy: { '/api': { ... } }`).
|
|
256
|
+
*/
|
|
257
|
+
function isProxyEntryObject(obj) {
|
|
258
|
+
const parent = obj.parent;
|
|
259
|
+
// Array form: proxy: [ { ... } ]
|
|
260
|
+
if (parent && ts.isArrayLiteralExpression(parent)) {
|
|
261
|
+
const arrProp = parent.parent;
|
|
262
|
+
return (!!arrProp &&
|
|
263
|
+
ts.isPropertyAssignment(arrProp) &&
|
|
264
|
+
getPropertyName(arrProp) === 'proxy');
|
|
265
|
+
}
|
|
266
|
+
// Object-map form: proxy: { '/api': { ... } }
|
|
267
|
+
if (parent && ts.isPropertyAssignment(parent)) {
|
|
268
|
+
const mapObj = parent.parent;
|
|
269
|
+
if (mapObj && ts.isObjectLiteralExpression(mapObj)) {
|
|
270
|
+
const mapProp = mapObj.parent;
|
|
271
|
+
return (!!mapProp &&
|
|
272
|
+
ts.isPropertyAssignment(mapProp) &&
|
|
273
|
+
getPropertyName(mapProp) === 'proxy');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Exported for unit testing. Renames the `context` matcher option to
|
|
280
|
+
* `pathFilter` inside `server.proxy` entries — http-proxy-middleware@4
|
|
281
|
+
* (pulled in by @rsbuild/core@2) renamed it. Anchored to a proxy entry
|
|
282
|
+
* so an unrelated `context` key elsewhere is left alone.
|
|
283
|
+
*/
|
|
284
|
+
function renameProxyContext(source) {
|
|
285
|
+
if (!source.includes('context'))
|
|
286
|
+
return source;
|
|
287
|
+
const sourceFile = (0, tsquery_1.ast)(source);
|
|
288
|
+
const edits = [];
|
|
289
|
+
const visit = (node) => {
|
|
290
|
+
if (ts.isPropertyAssignment(node) &&
|
|
291
|
+
getPropertyName(node) === 'context' &&
|
|
292
|
+
ts.isObjectLiteralExpression(node.parent) &&
|
|
293
|
+
isProxyEntryObject(node.parent)) {
|
|
294
|
+
edits.push({
|
|
295
|
+
start: node.name.getStart(sourceFile),
|
|
296
|
+
end: node.name.getEnd(),
|
|
297
|
+
replacement: 'pathFilter',
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
ts.forEachChild(node, visit);
|
|
301
|
+
};
|
|
302
|
+
visit(sourceFile);
|
|
303
|
+
return applyEdits(source, edits);
|
|
304
|
+
}
|
|
305
|
+
const PROXY_HANDLER_RENAMES = {
|
|
306
|
+
onOpen: 'open',
|
|
307
|
+
onClose: 'close',
|
|
308
|
+
onError: 'error',
|
|
309
|
+
onProxyReq: 'proxyReq',
|
|
310
|
+
onProxyRes: 'proxyRes',
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* Exported for unit testing. Consolidates the per-event proxy handlers
|
|
314
|
+
* (`onOpen`, `onClose`, `onError`, `onProxyReq`, `onProxyRes`) into a
|
|
315
|
+
* single `on: { open, close, error, proxyReq, proxyRes }` object —
|
|
316
|
+
* http-proxy-middleware@4's unified event API.
|
|
317
|
+
*
|
|
318
|
+
* Skips any proxy entry that already has an `on` property (already
|
|
319
|
+
* migrated). Anchored to proxy entries so unrelated `on*` keys are
|
|
320
|
+
* untouched.
|
|
321
|
+
*/
|
|
322
|
+
function groupProxyEventHandlers(source) {
|
|
323
|
+
if (!/\bon(Open|Close|Error|ProxyReq|ProxyRes)\b/.test(source)) {
|
|
324
|
+
return source;
|
|
325
|
+
}
|
|
326
|
+
const sourceFile = (0, tsquery_1.ast)(source);
|
|
327
|
+
const edits = [];
|
|
328
|
+
const visit = (node) => {
|
|
329
|
+
if (ts.isObjectLiteralExpression(node) && isProxyEntryObject(node)) {
|
|
330
|
+
const alreadyHasOn = node.properties.some((p) => ts.isPropertyAssignment(p) && getPropertyName(p) === 'on');
|
|
331
|
+
if (!alreadyHasOn) {
|
|
332
|
+
const handlers = node.properties.filter((p) => ts.isPropertyAssignment(p) &&
|
|
333
|
+
(getPropertyName(p) ?? '') in PROXY_HANDLER_RENAMES);
|
|
334
|
+
if (handlers.length > 0) {
|
|
335
|
+
const entries = handlers.map((p) => {
|
|
336
|
+
const newName = PROXY_HANDLER_RENAMES[getPropertyName(p)];
|
|
337
|
+
return `${newName}: ${p.initializer.getText(sourceFile)}`;
|
|
338
|
+
});
|
|
339
|
+
// Replace the first handler's range with the `on` block...
|
|
340
|
+
const first = handlers[0];
|
|
341
|
+
let firstEnd = first.getEnd();
|
|
342
|
+
const firstTrailing = source.slice(firstEnd).match(/^\s*,?\s*\r?\n?/);
|
|
343
|
+
if (firstTrailing)
|
|
344
|
+
firstEnd += firstTrailing[0].length;
|
|
345
|
+
edits.push({
|
|
346
|
+
start: first.getStart(sourceFile),
|
|
347
|
+
end: firstEnd,
|
|
348
|
+
replacement: `on: {\n${entries.map((e) => `${e},\n`).join('')}},\n`,
|
|
349
|
+
});
|
|
350
|
+
// ...and delete the remaining handlers.
|
|
351
|
+
for (const p of handlers.slice(1)) {
|
|
352
|
+
let end = p.getEnd();
|
|
353
|
+
const trailing = source.slice(end).match(/^\s*,?\s*\r?\n?/);
|
|
354
|
+
if (trailing)
|
|
355
|
+
end += trailing[0].length;
|
|
356
|
+
let start = p.getStart(sourceFile);
|
|
357
|
+
const lineStart = source.lastIndexOf('\n', start - 1) + 1;
|
|
358
|
+
if (source.slice(lineStart, start).trim() === '') {
|
|
359
|
+
start = lineStart;
|
|
360
|
+
}
|
|
361
|
+
edits.push({ start, end, replacement: '' });
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
ts.forEachChild(node, visit);
|
|
367
|
+
};
|
|
368
|
+
visit(sourceFile);
|
|
369
|
+
return applyEdits(source, edits);
|
|
370
|
+
}
|
|
@@ -74,7 +74,9 @@ async function createRsbuildTargets(configFilePath, projectRoot, options, tsConf
|
|
|
74
74
|
const absoluteConfigFilePath = (0, devkit_1.joinPathFragments)(context.workspaceRoot, configFilePath);
|
|
75
75
|
// Required lazily: `@rsbuild/core` is an optional peer dependency, so it
|
|
76
76
|
// may be absent when the plugin is loaded in a workspace that doesn't use
|
|
77
|
-
// Rsbuild yet (e.g. before a generator installs it).
|
|
77
|
+
// Rsbuild yet (e.g. before a generator installs it). This path runs in
|
|
78
|
+
// the CLI/daemon (never Jest), so a plain require works on Node 22.12+
|
|
79
|
+
// via require(esm) for the pure-ESM @rsbuild/core@2.
|
|
78
80
|
const { loadConfig } = require('@rsbuild/core');
|
|
79
81
|
const rsbuildConfig = await loadConfig({
|
|
80
82
|
path: absoluteConfigFilePath,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const nxVersion: any;
|
|
2
2
|
export declare const minSupportedRsbuildVersion = "1.0.0";
|
|
3
|
-
export declare const supportedRsbuildMajorVersions: readonly [1];
|
|
3
|
+
export declare const supportedRsbuildMajorVersions: readonly [2, 1];
|
|
4
4
|
export type SupportedRsbuildMajorVersion = (typeof supportedRsbuildMajorVersions)[number];
|
|
5
5
|
type RsbuildVersionMap = {
|
|
6
6
|
rsbuildVersion: string;
|
|
@@ -4,18 +4,26 @@ exports.rsbuildPluginSassVersion = exports.rsbuildPluginVueVersion = exports.rsb
|
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
exports.nxVersion = require((0, path_1.join)('@nx/rsbuild', 'package.json')).version;
|
|
6
6
|
exports.minSupportedRsbuildVersion = '1.0.0';
|
|
7
|
-
// Supported `@rsbuild/core` majors.
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
exports.supportedRsbuildMajorVersions = [1];
|
|
7
|
+
// Supported `@rsbuild/core` majors. v2 is the latest; v1 stays in the
|
|
8
|
+
// window for backward compatibility per the multi-version policy.
|
|
9
|
+
exports.supportedRsbuildMajorVersions = [2, 1];
|
|
11
10
|
exports.latestRsbuildVersions = {
|
|
12
|
-
rsbuildVersion: '
|
|
13
|
-
rsbuildPluginReactVersion: '
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
rsbuildVersion: '2.0.7',
|
|
12
|
+
rsbuildPluginReactVersion: '2.0.0',
|
|
13
|
+
// plugin-vue and plugin-sass still publish 1.x but declare compatibility
|
|
14
|
+
// with rsbuild ^1.0.0 || ^2.0.0-0, so the same range works on both
|
|
15
|
+
// majors.
|
|
16
|
+
rsbuildPluginVueVersion: '1.2.8',
|
|
17
|
+
rsbuildPluginSassVersion: '1.5.2',
|
|
16
18
|
};
|
|
17
19
|
exports.backwardCompatibleRsbuildVersions = {
|
|
18
|
-
|
|
20
|
+
2: exports.latestRsbuildVersions,
|
|
21
|
+
1: {
|
|
22
|
+
rsbuildVersion: '1.1.10',
|
|
23
|
+
rsbuildPluginReactVersion: '1.1.0',
|
|
24
|
+
rsbuildPluginVueVersion: '1.0.5',
|
|
25
|
+
rsbuildPluginSassVersion: '1.1.2',
|
|
26
|
+
},
|
|
19
27
|
};
|
|
20
28
|
/**
|
|
21
29
|
* Kept for backward compatibility with code paths that don't yet branch on
|
package/migrations.json
CHANGED
|
@@ -5,6 +5,51 @@
|
|
|
5
5
|
"description": "Rename imports of `createNodesV2` from `@nx/rsbuild` to the canonical `createNodes` export.",
|
|
6
6
|
"implementation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes",
|
|
7
7
|
"documentation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.md"
|
|
8
|
+
},
|
|
9
|
+
"update-23-0-0-migrate-rsbuild-config-to-v2": {
|
|
10
|
+
"cli": "nx",
|
|
11
|
+
"version": "23.1.0-beta.0",
|
|
12
|
+
"description": "Rewrites rsbuild.config.{js,ts,mjs,cjs} files for @rsbuild/core@2: renames preview.setupMiddlewares to server.setupMiddlewares, drops the removed performance.removeMomentLocale option, moves source.alias/source.aliasStrategy to the resolve block, and updates server.proxy entries for http-proxy-middleware v4 (context to pathFilter, on* handlers to a unified on object).",
|
|
13
|
+
"factory": "./dist/src/migrations/update-23-0-0/migrate-rsbuild-config-to-v2",
|
|
14
|
+
"requires": {
|
|
15
|
+
"@rsbuild/core": ">=2.0.0"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"update-23-0-0-migrate-node-output-to-esm": {
|
|
19
|
+
"cli": "nx",
|
|
20
|
+
"version": "23.1.0-beta.0",
|
|
21
|
+
"description": "AI-assisted migration: make Node-target rsbuild builds runnable under @rsbuild/core@2, which emits ESM output by default.",
|
|
22
|
+
"prompt": "./dist/src/migrations/update-23-0-0/migrate-node-output-to-esm.md",
|
|
23
|
+
"requires": {
|
|
24
|
+
"@rsbuild/core": ">=2.0.0"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"update-23-0-0-migrate-performance-options": {
|
|
28
|
+
"cli": "nx",
|
|
29
|
+
"version": "23.1.0-beta.0",
|
|
30
|
+
"description": "AI-assisted migration: adopt replacements for the performance.bundleAnalyze and performance.profile options removed in @rsbuild/core@2, and migrate the deprecated performance.chunkSplit option to splitChunks.",
|
|
31
|
+
"prompt": "./dist/src/migrations/update-23-0-0/migrate-performance-options.md",
|
|
32
|
+
"requires": {
|
|
33
|
+
"@rsbuild/core": ">=2.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"packageJsonUpdates": {
|
|
38
|
+
"23.0.0-rsbuild-v2": {
|
|
39
|
+
"version": "23.1.0-beta.0",
|
|
40
|
+
"requires": {
|
|
41
|
+
"@rsbuild/core": ">=1.0.0 <2.0.0"
|
|
42
|
+
},
|
|
43
|
+
"packages": {
|
|
44
|
+
"@rsbuild/core": {
|
|
45
|
+
"version": "^2.0.7",
|
|
46
|
+
"alwaysAddToPackageJson": false
|
|
47
|
+
},
|
|
48
|
+
"@rsbuild/plugin-react": {
|
|
49
|
+
"version": "^2.0.0",
|
|
50
|
+
"alwaysAddToPackageJson": false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
8
53
|
}
|
|
9
54
|
}
|
|
10
55
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/rsbuild",
|
|
3
3
|
"description": "The Nx Plugin for Rsbuild contains an Nx plugin, executors and utilities that support building applications using Rsbuild.",
|
|
4
|
-
"version": "23.0.0",
|
|
4
|
+
"version": "23.1.0-beta.0",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -57,14 +57,14 @@
|
|
|
57
57
|
"minimatch": "10.2.5",
|
|
58
58
|
"semver": "^7.6.3",
|
|
59
59
|
"@phenomnomnominal/tsquery": "~6.2.0",
|
|
60
|
-
"@nx/devkit": "23.0.0",
|
|
61
|
-
"@nx/js": "23.0.0"
|
|
60
|
+
"@nx/devkit": "23.1.0-beta.0",
|
|
61
|
+
"@nx/js": "23.1.0-beta.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"nx": "23.0.0"
|
|
64
|
+
"nx": "23.1.0-beta.0"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@rsbuild/core": "^1.0.0"
|
|
67
|
+
"@rsbuild/core": "^1.0.0 || ^2.0.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependenciesMeta": {
|
|
70
70
|
"@rsbuild/core": {
|