diff options
author | 2024-05-07 13:13:03 -0400 | |
---|---|---|
committer | 2024-05-07 13:13:03 -0400 | |
commit | d47baa466aaeedde9c79ed5375d0be34762ac8b6 (patch) | |
tree | bc12edbce6cde5150ec4d654dcee1e20c8a95513 /packages/integrations/react/src | |
parent | 4b693c0476f04a6956208a5df42c52a70a559fda (diff) | |
download | astro-d47baa466aaeedde9c79ed5375d0be34762ac8b6.tar.gz astro-d47baa466aaeedde9c79ed5375d0be34762ac8b6.tar.zst astro-d47baa466aaeedde9c79ed5375d0be34762ac8b6.zip |
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>
Diffstat (limited to 'packages/integrations/react/src')
-rw-r--r-- | packages/integrations/react/src/index.ts | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/packages/integrations/react/src/index.ts b/packages/integrations/react/src/index.ts index e0149e8e7..62803e788 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 = /\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__`, '/'); |