0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Support React 19 (#10942)

* Support React 19

* Fix lint

* Update .changeset/short-phones-breathe.md

* fix: update types peer dep

---------

Co-authored-by: bholmesdev <hey@bholmes.dev>
This commit is contained in:
Matthew Phillips 2024-05-07 13:13:03 -04:00 committed by GitHub
parent 4b693c0476
commit d47baa466a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 57 additions and 23 deletions

View file

@ -0,0 +1,5 @@
---
"@astrojs/react": patch
---
Updates package to support React 19 beta

View file

@ -60,10 +60,10 @@
"vite": "^5.2.10"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",
"@types/react-dom": "^17.0.17 || ^18.0.6",
"react": "^17.0.2 || ^18.0.0",
"react-dom": "^17.0.2 || ^18.0.0"
"@types/react": "^17.0.50 || ^18.0.21 || npm:types-react@beta",
"@types/react-dom": "^17.0.17 || ^18.0.6 || npm:types-react-dom@beta",
"react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta",
"react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta"
},
"engines": {
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"

View file

@ -12,15 +12,44 @@ export type ReactIntegrationOptions = Pick<
const FAST_REFRESH_PREAMBLE = react.preambleCode;
function getRenderer() {
const versionsConfig = {
17: {
server: '@astrojs/react/server-v17.js',
client: '@astrojs/react/client-v17.js',
externals: ['react-dom/server.js', 'react-dom/client.js'],
},
18: {
server: '@astrojs/react/server.js',
client: '@astrojs/react/client.js',
externals: ['react-dom/server', 'react-dom/client']
},
19: {
server: '@astrojs/react/server.js',
client: '@astrojs/react/client.js',
externals: ['react-dom/server', 'react-dom/client']
}
};
type SupportedReactVersion = keyof (typeof versionsConfig);
type ReactVersionConfig = (typeof versionsConfig)[SupportedReactVersion];
function getReactMajorVersion(): number {
const matches = /\d+\./.exec(ReactVersion);
if(!matches) {
return NaN;
}
return Number(matches[0]);
}
function isUnsupportedVersion(majorVersion: number) {
return majorVersion < 17 || majorVersion > 19 || Number.isNaN(majorVersion);
}
function getRenderer(reactConfig: ReactVersionConfig) {
return {
name: '@astrojs/react',
clientEntrypoint: ReactVersion.startsWith('18.')
? '@astrojs/react/client.js'
: '@astrojs/react/client-v17.js',
serverEntrypoint: ReactVersion.startsWith('18.')
? '@astrojs/react/server.js'
: '@astrojs/react/server-v17.js',
clientEntrypoint: reactConfig.client,
serverEntrypoint: reactConfig.server,
};
}
@ -51,22 +80,18 @@ function getViteConfiguration({
exclude,
babel,
experimentalReactChildren,
}: ReactIntegrationOptions = {}) {
}: ReactIntegrationOptions = {}, reactConfig: ReactVersionConfig) {
return {
optimizeDeps: {
include: [
ReactVersion.startsWith('18.')
? '@astrojs/react/client.js'
: '@astrojs/react/client-v17.js',
reactConfig.client,
'react',
'react/jsx-runtime',
'react/jsx-dev-runtime',
'react-dom',
],
exclude: [
ReactVersion.startsWith('18.')
? '@astrojs/react/server.js'
: '@astrojs/react/server-v17.js',
reactConfig.server,
],
},
plugins: [react({ include, exclude, babel }), optionsPlugin(!!experimentalReactChildren)],
@ -74,9 +99,7 @@ function getViteConfiguration({
dedupe: ['react', 'react-dom', 'react-dom/server'],
},
ssr: {
external: ReactVersion.startsWith('18.')
? ['react-dom/server', 'react-dom/client']
: ['react-dom/server.js', 'react-dom/client.js'],
external: reactConfig.externals,
noExternal: [
// These are all needed to get mui to work.
'@mui/material',
@ -95,13 +118,19 @@ export default function ({
babel,
experimentalReactChildren,
}: ReactIntegrationOptions = {}): AstroIntegration {
const majorVersion = getReactMajorVersion();
if(isUnsupportedVersion(majorVersion)) {
throw new Error(`Unsupported React version: ${majorVersion}.`);
}
const versionConfig = versionsConfig[majorVersion as SupportedReactVersion];
return {
name: '@astrojs/react',
hooks: {
'astro:config:setup': ({ command, addRenderer, updateConfig, injectScript }) => {
addRenderer(getRenderer());
addRenderer(getRenderer(versionConfig));
updateConfig({
vite: getViteConfiguration({ include, exclude, babel, experimentalReactChildren }),
vite: getViteConfiguration({ include, exclude, babel, experimentalReactChildren }, versionConfig),
});
if (command === 'dev') {
const preamble = FAST_REFRESH_PREAMBLE.replace(`__BASE__`, '/');