diff --git a/.changeset/three-steaks-exist.md b/.changeset/three-steaks-exist.md new file mode 100644 index 000000000000..a42092410e89 --- /dev/null +++ b/.changeset/three-steaks-exist.md @@ -0,0 +1,21 @@ +--- +"@astrojs/react": minor +--- + +Adds experimental support for disabling streaming + +This is useful to support libraries that are not compatible with streaming such as some CSS-in-JS libraries. To disable streaming for all React components in your project, set `experimentalDisableStreaming: true` as a configuration option for `@astrojs/react`: + +```diff +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import react from '@astrojs/react'; + +export default defineConfig({ + integrations: [ + react({ ++ experimentalDisableStreaming: true, + }), + ], +}); +``` diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js index 50d6bd94bbe3..67d9e938659b 100644 --- a/packages/integrations/react/server.js +++ b/packages/integrations/react/server.js @@ -101,7 +101,9 @@ async function renderToStaticMarkup(Component, props, { default: children, ...sl formState, }; let html; - if ('renderToReadableStream' in ReactDOM) { + if (opts.experimentalDisableStreaming) { + html = ReactDOM.renderToString(vnode); + } else if ('renderToReadableStream' in ReactDOM) { html = await renderToReadableStreamAsync(vnode, renderOptions); } else { html = await renderToPipeableStreamAsync(vnode, renderOptions); diff --git a/packages/integrations/react/src/index.ts b/packages/integrations/react/src/index.ts index 1d88b09e1ff1..f0683ada71a5 100644 --- a/packages/integrations/react/src/index.ts +++ b/packages/integrations/react/src/index.ts @@ -14,6 +14,10 @@ export type ReactIntegrationOptions = Pick< 'include' | 'exclude' | 'babel' > & { experimentalReactChildren?: boolean; + /** + * Disable streaming in React components + */ + experimentalDisableStreaming?: boolean; }; const FAST_REFRESH_PREAMBLE = react.preambleCode; @@ -26,7 +30,13 @@ function getRenderer(reactConfig: ReactVersionConfig) { }; } -function optionsPlugin(experimentalReactChildren: boolean): vite.Plugin { +function optionsPlugin({ + experimentalReactChildren = false, + experimentalDisableStreaming = false +}: { + experimentalReactChildren: boolean; + experimentalDisableStreaming: boolean; +}): vite.Plugin { const virtualModule = 'astro:react:opts'; const virtualModuleId = '\0' + virtualModule; return { @@ -40,7 +50,8 @@ function optionsPlugin(experimentalReactChildren: boolean): vite.Plugin { if (id === virtualModuleId) { return { code: `export default { - experimentalReactChildren: ${JSON.stringify(experimentalReactChildren)} + experimentalReactChildren: ${JSON.stringify(experimentalReactChildren)}, + experimentalDisableStreaming: ${JSON.stringify(experimentalDisableStreaming)} }`, }; } @@ -49,7 +60,7 @@ function optionsPlugin(experimentalReactChildren: boolean): vite.Plugin { } function getViteConfiguration( - { include, exclude, babel, experimentalReactChildren }: ReactIntegrationOptions = {}, + { include, exclude, babel, experimentalReactChildren, experimentalDisableStreaming }: ReactIntegrationOptions = {}, reactConfig: ReactVersionConfig, ) { return { @@ -57,7 +68,12 @@ function getViteConfiguration( include: [reactConfig.client], exclude: [reactConfig.server], }, - plugins: [react({ include, exclude, babel }), optionsPlugin(!!experimentalReactChildren)], + plugins: [ + react({ include, exclude, babel }), + optionsPlugin({ + experimentalReactChildren: !!experimentalReactChildren, experimentalDisableStreaming: !!experimentalDisableStreaming + }), + ], ssr: { noExternal: [ // These are all needed to get mui to work. @@ -76,6 +92,7 @@ export default function ({ exclude, babel, experimentalReactChildren, + experimentalDisableStreaming, }: ReactIntegrationOptions = {}): AstroIntegration { const majorVersion = getReactMajorVersion(); if (isUnsupportedVersion(majorVersion)) { @@ -90,7 +107,7 @@ export default function ({ addRenderer(getRenderer(versionConfig)); updateConfig({ vite: getViteConfiguration( - { include, exclude, babel, experimentalReactChildren }, + { include, exclude, babel, experimentalReactChildren, experimentalDisableStreaming }, versionConfig, ), });