Skip to content

Commit 4e6fe61

Browse files
slorberclaude
andauthored
refactor(bundler): target the current Node.js version for server builds, remove the hardcoded 26.0.0 clamp (AI-assisted) (#12781)
SWC no longer falls back to ES5 for Node.js versions newer than its Browserslist data: it now skips all transforms for them, like Babel (swc-project/swc#11457, shipped in every Rspack 2.x). The server target is the current Node.js version without its pre-release tag, because SWC panics on versions like "27.0.0-rc.1". Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 6d54337 commit 4e6fe61

5 files changed

Lines changed: 50 additions & 46 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import {afterEach, describe, expect, it, vi} from 'vitest';
9+
import {getTargets} from '../browserslist';
10+
11+
const realNodeVersion = process.versions.node;
12+
13+
function stubNodeVersion(version: string) {
14+
Object.defineProperty(process.versions, 'node', {value: version});
15+
}
16+
17+
describe('getTargets', () => {
18+
describe('server', () => {
19+
afterEach(() => {
20+
stubNodeVersion(realNodeVersion);
21+
vi.unstubAllEnvs();
22+
});
23+
24+
it('targets the current Node.js version', () => {
25+
stubNodeVersion('26.8.1');
26+
expect(getTargets({isServer: true})).toEqual(['node 26.8.1']);
27+
});
28+
29+
it('removes the pre-release tag of the current Node.js version', () => {
30+
stubNodeVersion('27.0.0-rc.1');
31+
expect(getTargets({isServer: true})).toEqual(['node 27.0.0']);
32+
});
33+
34+
it('targets the DOCUSAURUS_SERVER_NODE_TARGET env variable', () => {
35+
vi.stubEnv('DOCUSAURUS_SERVER_NODE_TARGET', '24.18.0');
36+
expect(getTargets({isServer: true})).toEqual(['node 24.18.0']);
37+
});
38+
});
39+
});

‎packages/docusaurus-bundler/src/browserslist.ts‎

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import browserslist from 'browserslist';
99
import semver from 'semver';
1010
import {browserslistToTargets, type TransformOptions} from 'lightningcss';
11-
import type {CurrentBundler} from '@docusaurus/types';
1211

1312
// Used when the site doesn't provide its own Browserslist config
1413
// See https://web.dev/baseline
@@ -18,14 +17,8 @@ const DefaultBrowserslistQueries = ['baseline widely available'];
1817
* The targets the client or server bundle is compiled for, like
1918
* `['chrome 120', 'firefox 115']` or `['node 24.11.1']`
2019
*/
21-
export function getTargets({
22-
isServer,
23-
bundlerName,
24-
}: {
25-
isServer: boolean;
26-
bundlerName: CurrentBundler['name'];
27-
}): string[] {
28-
return isServer ? getServerTargets({bundlerName}) : getClientTargets();
20+
export function getTargets({isServer}: {isServer: boolean}): string[] {
21+
return isServer ? getServerTargets() : getClientTargets();
2922
}
3023

3124
export function getClientQueries(): string[] {
@@ -42,41 +35,16 @@ function getClientTargets(): string[] {
4235
return browserslist(getClientQueries());
4336
}
4437

45-
export function getServerTargets({
46-
bundlerName,
47-
}: {
48-
bundlerName: CurrentBundler['name'];
49-
}): string[] {
38+
// SWC skips all transforms for Node versions newer than its Browserslist data
39+
// See https://github.com/swc-project/swc/pull/11457
40+
export function getServerTargets(): string[] {
5041
// Escape hatch env variable
5142
if (process.env.DOCUSAURUS_SERVER_NODE_TARGET) {
5243
return [`node ${process.env.DOCUSAURUS_SERVER_NODE_TARGET}`];
5344
}
54-
// For server builds, we want to use the current Node version as target
55-
// But we can't pass a target that Browserslist doesn't know about yet
56-
const nodeTarget = getMinVersion(
57-
process.versions.node,
58-
getLastBrowserslistKnownNodeVersion(bundlerName),
59-
);
60-
return [`node ${nodeTarget}`];
61-
}
62-
63-
// TODO this is not accurate
64-
// for Rspack we should read from the built-in browserslist data
65-
// see https://github.com/facebook/docusaurus/pull/11496
66-
function getLastBrowserslistKnownNodeVersion(
67-
bundlerName: CurrentBundler['name'],
68-
): string {
69-
if (bundlerName === 'rspack') {
70-
// TODO hardcoded value until Rspack exposes its Browserslist data
71-
// see https://github.com/facebook/docusaurus/pull/11496
72-
return '26.0.0';
73-
}
74-
// browserslist('last 1 node versions')[0]!.replace('node ', '')
75-
return browserslist.nodeVersions.at(-1)!;
76-
}
77-
78-
function getMinVersion(v1: string, v2: string): string {
79-
return semver.lt(v1, v2) ? v1 : v2;
45+
// SWC panics on pre-release versions like "27.0.0-rc.1"
46+
const nodeVersion = semver.coerce(process.versions.node)!.version;
47+
return [`node ${nodeVersion}`];
8048
}
8149

8250
// LightningCSS doesn't expose any type for minimizer-webpack-plugin setup

‎packages/docusaurus-bundler/src/loaders/jsLoader.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function createRspackSwcJsLoaderFactory(): ConfigureWebpackUtils['getJSLoader']
2929
return ({isServer}) => {
3030
return {
3131
loader,
32-
options: getSwcLoaderOptions({isServer, bundlerName: 'rspack'}),
32+
options: getSwcLoaderOptions({isServer}),
3333
};
3434
};
3535
}

‎packages/docusaurus-bundler/src/swc.ts‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,16 @@
77

88
import {getClientQueries, getServerTargets} from './browserslist';
99
import type {SwcLoaderOptions} from '@rspack/core';
10-
import type {CurrentBundler} from '@docusaurus/types';
1110

1211
export function getSwcLoaderOptions({
1312
isServer,
14-
bundlerName,
1513
}: {
1614
isServer: boolean;
17-
bundlerName: CurrentBundler['name'];
1815
}): SwcLoaderOptions {
1916
return {
2017
env: {
2118
// Rspack resolves the client queries with its own Browserslist data
22-
targets: isServer ? getServerTargets({bundlerName}) : getClientQueries(),
19+
targets: isServer ? getServerTargets() : getClientQueries(),
2320
},
2421
jsc: {
2522
parser: {

‎packages/docusaurus/src/webpack/base.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export async function createBaseConfig({
118118
// Changing the target browsers or Node.js version must evict the cache
119119
// The same Browserslist queries can match other browsers over time and
120120
// after data upgrades, for example "baseline widely available"
121-
getTargets({isServer, bundlerName: props.currentBundler.name}),
121+
getTargets({isServer}),
122122
// The plugin code computing loader options is not a build dependency
123123
// Upgrading a third-party plugin must evict the cache
124124
siteMetadata.pluginVersions,

0 commit comments

Comments
 (0)