Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support React 19 #10942

Merged
merged 4 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/short-phones-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@astrojs/react": patch
---

Updates package to support React 19 beta
8 changes: 4 additions & 4 deletions packages/integrations/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
67 changes: 48 additions & 19 deletions packages/integrations/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}

Expand Down Expand Up @@ -51,32 +80,26 @@ 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)],
resolve: {
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',
Expand All @@ -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__`, '/');
Expand Down
Loading