Skip to content

Commit d47baa4

Browse files
matthewpbholmesdev
andauthored
Support React 19 (#10942)
* Support React 19 * Fix lint * Update .changeset/short-phones-breathe.md * fix: update types peer dep --------- Co-authored-by: bholmesdev <[email protected]>
1 parent 4b693c0 commit d47baa4

File tree

3 files changed

+57
-23
lines changed

3 files changed

+57
-23
lines changed

.changeset/short-phones-breathe.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@astrojs/react": patch
3+
---
4+
5+
Updates package to support React 19 beta

packages/integrations/react/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@
6060
"vite": "^5.2.10"
6161
},
6262
"peerDependencies": {
63-
"@types/react": "^17.0.50 || ^18.0.21",
64-
"@types/react-dom": "^17.0.17 || ^18.0.6",
65-
"react": "^17.0.2 || ^18.0.0",
66-
"react-dom": "^17.0.2 || ^18.0.0"
63+
"@types/react": "^17.0.50 || ^18.0.21 || npm:types-react@beta",
64+
"@types/react-dom": "^17.0.17 || ^18.0.6 || npm:types-react-dom@beta",
65+
"react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta",
66+
"react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta"
6767
},
6868
"engines": {
6969
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"

packages/integrations/react/src/index.ts

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,44 @@ export type ReactIntegrationOptions = Pick<
1212

1313
const FAST_REFRESH_PREAMBLE = react.preambleCode;
1414

15-
function getRenderer() {
15+
const versionsConfig = {
16+
17: {
17+
server: '@astrojs/react/server-v17.js',
18+
client: '@astrojs/react/client-v17.js',
19+
externals: ['react-dom/server.js', 'react-dom/client.js'],
20+
},
21+
18: {
22+
server: '@astrojs/react/server.js',
23+
client: '@astrojs/react/client.js',
24+
externals: ['react-dom/server', 'react-dom/client']
25+
},
26+
19: {
27+
server: '@astrojs/react/server.js',
28+
client: '@astrojs/react/client.js',
29+
externals: ['react-dom/server', 'react-dom/client']
30+
}
31+
};
32+
33+
type SupportedReactVersion = keyof (typeof versionsConfig);
34+
type ReactVersionConfig = (typeof versionsConfig)[SupportedReactVersion];
35+
36+
function getReactMajorVersion(): number {
37+
const matches = /\d+\./.exec(ReactVersion);
38+
if(!matches) {
39+
return NaN;
40+
}
41+
return Number(matches[0]);
42+
}
43+
44+
function isUnsupportedVersion(majorVersion: number) {
45+
return majorVersion < 17 || majorVersion > 19 || Number.isNaN(majorVersion);
46+
}
47+
48+
function getRenderer(reactConfig: ReactVersionConfig) {
1649
return {
1750
name: '@astrojs/react',
18-
clientEntrypoint: ReactVersion.startsWith('18.')
19-
? '@astrojs/react/client.js'
20-
: '@astrojs/react/client-v17.js',
21-
serverEntrypoint: ReactVersion.startsWith('18.')
22-
? '@astrojs/react/server.js'
23-
: '@astrojs/react/server-v17.js',
51+
clientEntrypoint: reactConfig.client,
52+
serverEntrypoint: reactConfig.server,
2453
};
2554
}
2655

@@ -51,32 +80,26 @@ function getViteConfiguration({
5180
exclude,
5281
babel,
5382
experimentalReactChildren,
54-
}: ReactIntegrationOptions = {}) {
83+
}: ReactIntegrationOptions = {}, reactConfig: ReactVersionConfig) {
5584
return {
5685
optimizeDeps: {
5786
include: [
58-
ReactVersion.startsWith('18.')
59-
? '@astrojs/react/client.js'
60-
: '@astrojs/react/client-v17.js',
87+
reactConfig.client,
6188
'react',
6289
'react/jsx-runtime',
6390
'react/jsx-dev-runtime',
6491
'react-dom',
6592
],
6693
exclude: [
67-
ReactVersion.startsWith('18.')
68-
? '@astrojs/react/server.js'
69-
: '@astrojs/react/server-v17.js',
94+
reactConfig.server,
7095
],
7196
},
7297
plugins: [react({ include, exclude, babel }), optionsPlugin(!!experimentalReactChildren)],
7398
resolve: {
7499
dedupe: ['react', 'react-dom', 'react-dom/server'],
75100
},
76101
ssr: {
77-
external: ReactVersion.startsWith('18.')
78-
? ['react-dom/server', 'react-dom/client']
79-
: ['react-dom/server.js', 'react-dom/client.js'],
102+
external: reactConfig.externals,
80103
noExternal: [
81104
// These are all needed to get mui to work.
82105
'@mui/material',
@@ -95,13 +118,19 @@ export default function ({
95118
babel,
96119
experimentalReactChildren,
97120
}: ReactIntegrationOptions = {}): AstroIntegration {
121+
const majorVersion = getReactMajorVersion();
122+
if(isUnsupportedVersion(majorVersion)) {
123+
throw new Error(`Unsupported React version: ${majorVersion}.`);
124+
}
125+
const versionConfig = versionsConfig[majorVersion as SupportedReactVersion];
126+
98127
return {
99128
name: '@astrojs/react',
100129
hooks: {
101130
'astro:config:setup': ({ command, addRenderer, updateConfig, injectScript }) => {
102-
addRenderer(getRenderer());
131+
addRenderer(getRenderer(versionConfig));
103132
updateConfig({
104-
vite: getViteConfiguration({ include, exclude, babel, experimentalReactChildren }),
133+
vite: getViteConfiguration({ include, exclude, babel, experimentalReactChildren }, versionConfig),
105134
});
106135
if (command === 'dev') {
107136
const preamble = FAST_REFRESH_PREAMBLE.replace(`__BASE__`, '/');

0 commit comments

Comments
 (0)