From 9355dca1420fd013163a42826ed508684de58bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Rialland?= Date: Thu, 7 Sep 2023 14:53:52 +0200 Subject: [PATCH] Fix prerender --- site/build/prerender-worker.ts | 25 +++++-------- site/source/components/Provider.tsx | 56 +++++++++++++++------------- site/source/entries/entry-fr.tsx | 16 ++++++-- site/source/entries/entry-server.tsx | 10 +++-- site/source/entries/template.html | 2 + site/source/pages/Documentation.tsx | 31 ++++++++++++--- 6 files changed, 86 insertions(+), 54 deletions(-) diff --git a/site/build/prerender-worker.ts b/site/build/prerender-worker.ts index 87cf417b8..1ee58cb10 100644 --- a/site/build/prerender-worker.ts +++ b/site/build/prerender-worker.ts @@ -22,32 +22,25 @@ interface Params { lang: string } -// const vite = await createViteServer({ -// server: {}, -// appType: 'mpa', -// }) +const script = ` + +` export default async ({ site, url, lang }: Params) => { - const fileTemplate = + const template = cache[site] ?? readFileSync(path.join(dirname, `../dist/${site}.html`), 'utf-8') - cache[site] ??= fileTemplate + cache[site] ??= template - // const template = await vite.transformIndexHtml(url, fileTemplate) - const template = fileTemplate - - // const { render } = await vite.ssrLoadModule( - // './source/entries/entry-server.tsx' - // ) - - // TODO: Add CI test to enforce meta tags on SSR pages + // // TODO: Add CI test to enforce meta tags on SSR pages const { html, styleTags, helmet } = await render(url, lang) - console.log({ html, styleTags, helmet }) - const page = template .replace(regexHTML, html) + .replace('', script) .replace('', styleTags) .replace(regexHelmet, helmet.title.toString() + helmet.meta.toString()) diff --git a/site/source/components/Provider.tsx b/site/source/components/Provider.tsx index efbede62e..332b9e7da 100644 --- a/site/source/components/Provider.tsx +++ b/site/source/components/Provider.tsx @@ -1,6 +1,10 @@ import NodeWorker from '@eshaz/web-worker' import { createWorkerEngineClient } from '@publicodes/worker' -import { useWorkerEngine, WorkerEngineProvider } from '@publicodes/worker-react' +import { + SuspensePromise, + useWorkerEngine, + WorkerEngineProvider, +} from '@publicodes/worker-react' import { OverlayProvider } from '@react-aria/overlays' import { ErrorBoundary } from '@sentry/react' import i18next from 'i18next' @@ -80,30 +84,32 @@ export default function Provider({ - - - ( - // eslint-disable-next-line react/jsx-props-no-spreading - - )} - > - {!import.meta.env.SSR && - import.meta.env.MODE === 'production' && - 'serviceWorker' in navigator && } - - - - - - {children} - - - - - - - + + + + ( + // eslint-disable-next-line react/jsx-props-no-spreading + + )} + > + {!import.meta.env.SSR && + import.meta.env.MODE === 'production' && + 'serviceWorker' in navigator && } + + + + + + {children} + + + + + + + + diff --git a/site/source/entries/entry-fr.tsx b/site/source/entries/entry-fr.tsx index 70883fbc1..54bbf2e93 100644 --- a/site/source/entries/entry-fr.tsx +++ b/site/source/entries/entry-fr.tsx @@ -1,12 +1,18 @@ import { I18nProvider } from '@react-aria/i18n' import { withProfiler } from '@sentry/react' -import { createRoot } from 'react-dom/client' +import { createRoot, hydrateRoot } from 'react-dom/client' import App from '../components/App' import i18next from '../locales/i18n' import '../api/sentry' +declare global { + interface Window { + PRERENDER?: boolean + } +} + export const AppFr = () => { return ( @@ -23,6 +29,10 @@ if (!import.meta.env.SSR) { console.error(err) ) const container = document.querySelector('#js') as Element - const root = createRoot(container) - root.render() + if (window.PRERENDER) { + const root = hydrateRoot(container, ) + } else { + const root = createRoot(container) + root.render() + } } diff --git a/site/source/entries/entry-server.tsx b/site/source/entries/entry-server.tsx index 4e76496d9..5fce28906 100644 --- a/site/source/entries/entry-server.tsx +++ b/site/source/entries/entry-server.tsx @@ -1,12 +1,16 @@ import { SSRProvider } from '@react-aria/ssr' import { lazy } from 'react' -import ReactDomServer, { type renderToReadableStream } from 'react-dom/server' +import ReactDomServerType from 'react-dom/server' +// @ts-ignore +import ReactDomServer from 'react-dom/server.browser' import { FilledContext, HelmetProvider } from 'react-helmet-async' import { StaticRouter } from 'react-router-dom/server' import { ServerStyleSheet, StyleSheetManager } from 'styled-components' import i18next from '../locales/i18n' +const { renderToReadableStream } = ReactDomServer as typeof ReactDomServerType + function streamToString(stream: ReadableStream) { return new Response(stream).text() } @@ -59,9 +63,7 @@ export async function render(url: string, lang: 'fr' | 'en'): Promise { console.log('!!! STARTING !!!') try { - const stream = await ( - ReactDomServer.renderToReadableStream as unknown as typeof renderToReadableStream - )(element, { + const stream = await renderToReadableStream(element, { onError(error, errorInfo) { console.error({ error, errorInfo }) }, diff --git a/site/source/entries/template.html b/site/source/entries/template.html index b6ec2e3d2..794b78620 100644 --- a/site/source/entries/template.html +++ b/site/source/entries/template.html @@ -230,6 +230,8 @@ } + +