From fd218d2ceb5034df3ceb1b870ca571d698543c02 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Fri, 3 May 2024 09:52:10 -0400 Subject: [PATCH 1/4] Support React 19 --- .changeset/short-phones-breathe.md | 5 ++ packages/integrations/react/package.json | 4 +- packages/integrations/react/src/index.ts | 67 +++++++++++++++++------- 3 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 .changeset/short-phones-breathe.md diff --git a/.changeset/short-phones-breathe.md b/.changeset/short-phones-breathe.md new file mode 100644 index 000000000000..4699e8674060 --- /dev/null +++ b/.changeset/short-phones-breathe.md @@ -0,0 +1,5 @@ +--- +"@astrojs/react": patch +--- + +Support React 19 diff --git a/packages/integrations/react/package.json b/packages/integrations/react/package.json index 90eaba4c3f3d..af46747b900c 100644 --- a/packages/integrations/react/package.json +++ b/packages/integrations/react/package.json @@ -62,8 +62,8 @@ "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" + "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" diff --git a/packages/integrations/react/src/index.ts b/packages/integrations/react/src/index.ts index e0149e8e76c1..dd94b6b94997 100644 --- a/packages/integrations/react/src/index.ts +++ b/packages/integrations/react/src/index.ts @@ -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 = /[0-9]+\./.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 version`); + } + 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__`, '/'); From 45bbcfc7f5901fa252d2606cbc7c2eee516e648c Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Fri, 3 May 2024 11:20:29 -0400 Subject: [PATCH 2/4] Fix lint --- packages/integrations/react/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/integrations/react/src/index.ts b/packages/integrations/react/src/index.ts index dd94b6b94997..62803e788c8f 100644 --- a/packages/integrations/react/src/index.ts +++ b/packages/integrations/react/src/index.ts @@ -34,7 +34,7 @@ type SupportedReactVersion = keyof (typeof versionsConfig); type ReactVersionConfig = (typeof versionsConfig)[SupportedReactVersion]; function getReactMajorVersion(): number { - const matches = /[0-9]+\./.exec(ReactVersion); + const matches = /\d+\./.exec(ReactVersion); if(!matches) { return NaN; } @@ -120,7 +120,7 @@ export default function ({ }: ReactIntegrationOptions = {}): AstroIntegration { const majorVersion = getReactMajorVersion(); if(isUnsupportedVersion(majorVersion)) { - throw new Error(`Unsupported version`); + throw new Error(`Unsupported React version: ${majorVersion}.`); } const versionConfig = versionsConfig[majorVersion as SupportedReactVersion]; From 1a665f735de1553ac5203e58ad28dbe4200a072a Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Fri, 3 May 2024 12:16:58 -0400 Subject: [PATCH 3/4] Update .changeset/short-phones-breathe.md --- .changeset/short-phones-breathe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/short-phones-breathe.md b/.changeset/short-phones-breathe.md index 4699e8674060..d27d015afbec 100644 --- a/.changeset/short-phones-breathe.md +++ b/.changeset/short-phones-breathe.md @@ -2,4 +2,4 @@ "@astrojs/react": patch --- -Support React 19 +Updates package to support React 19 beta From 5770ff856b80124651abf63b34be3e9377aba702 Mon Sep 17 00:00:00 2001 From: bholmesdev Date: Mon, 6 May 2024 11:34:24 -0400 Subject: [PATCH 4/4] fix: update types peer dep --- packages/integrations/react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/integrations/react/package.json b/packages/integrations/react/package.json index af46747b900c..e088be21d8cc 100644 --- a/packages/integrations/react/package.json +++ b/packages/integrations/react/package.json @@ -60,8 +60,8 @@ "vite": "^5.2.10" }, "peerDependencies": { - "@types/react": "^17.0.50 || ^18.0.21", - "@types/react-dom": "^17.0.17 || ^18.0.6", + "@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" },