From 72b20ec699ee6dd53dc0ba4333bc3bc614f18795 Mon Sep 17 00:00:00 2001 From: Muhammad Date: Fri, 6 Sep 2024 23:51:36 +0700 Subject: [PATCH] fix(useConfig): add support for `useConfig()` with HTML streaming --- .../hooks/useConfig/useConfig-server.ts | 19 +++++++++++++++++-- .../vike-solid/integration/onRenderHtml.tsx | 14 +++++++++++--- packages/vike-solid/types/Config.ts | 1 + packages/vike-solid/types/PageContext.ts | 3 ++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/vike-solid/hooks/useConfig/useConfig-server.ts b/packages/vike-solid/hooks/useConfig/useConfig-server.ts index 04464d5..056cfda 100644 --- a/packages/vike-solid/hooks/useConfig/useConfig-server.ts +++ b/packages/vike-solid/hooks/useConfig/useConfig-server.ts @@ -1,7 +1,7 @@ export { useConfig }; import type { PageContext } from "vike/types"; import type { PageContextInternal } from "../../types/PageContext.js"; -import type { ConfigFromHook } from "../../types/Config.js"; +import type { ConfigFromHook, Stream } from "../../types/Config.js"; import { usePageContext } from "../usePageContext.js"; import { getPageContext } from "vike/getPageContext"; import { objectKeys } from "../../utils/objectKeys.js"; @@ -20,7 +20,14 @@ function useConfig(): (config: ConfigFromHook) => void { // Component pageContext = usePageContext(); - return (config: ConfigFromHook) => setPageContextConfigFromHook(config, pageContext); + return (config: ConfigFromHook) => { + if (!pageContext._headAlreadySet) { + setPageContextConfigFromHook(config, pageContext); + } else { + // already sent to the browser => send DOM-manipulating scripts during HTML streaming + apply(config, pageContext._stream!); + } + }; } const configsClientSide = ["title"]; @@ -44,3 +51,11 @@ function setPageContextConfigFromHook(config: ConfigFromHook, pageContext: PageC } }); } + +function apply(config: ConfigFromHook, stream: Stream) { + const { title } = config; + if (title) { + const htmlSnippet = ``; + stream.write(htmlSnippet); + } +} diff --git a/packages/vike-solid/integration/onRenderHtml.tsx b/packages/vike-solid/integration/onRenderHtml.tsx index aef1b9b..79c907a 100644 --- a/packages/vike-solid/integration/onRenderHtml.tsx +++ b/packages/vike-solid/integration/onRenderHtml.tsx @@ -40,16 +40,24 @@ const onRenderHtml: OnRenderHtmlAsync = async ( `; }; -function getPageHtml(pageContext: PageContextServer) { +function getPageHtml(pageContext: PageContextServer & PageContextInternal) { let pageHtml: string | ReturnType | TPipe = ""; if (pageContext.Page) { if (!pageContext.config.stream) { pageHtml = dangerouslySkipEscape(renderToString(() => getPageElement(pageContext))); } else if (pageContext.config.stream === "web") { - pageHtml = renderToStream(() => getPageElement(pageContext)).pipeTo; + pageHtml = renderToStream(() => getPageElement(pageContext), { + onCompleteShell(info) { + pageContext._stream ??= info; + }, + }).pipeTo; stampPipe(pageHtml, "web-stream"); } else { - pageHtml = renderToStream(() => getPageElement(pageContext)).pipe; + pageHtml = renderToStream(() => getPageElement(pageContext), { + onCompleteShell(info) { + pageContext._stream ??= info; + }, + }).pipe; stampPipe(pageHtml, "node-stream"); } } diff --git a/packages/vike-solid/types/Config.ts b/packages/vike-solid/types/Config.ts index ca4b84b..14250b1 100644 --- a/packages/vike-solid/types/Config.ts +++ b/packages/vike-solid/types/Config.ts @@ -186,3 +186,4 @@ export type ConfigFromHook = PickWithoutGetter< >; export type ConfigFromHookResolved = Omit & Pick; +export type Stream = { write: (v: string) => void }; diff --git a/packages/vike-solid/types/PageContext.ts b/packages/vike-solid/types/PageContext.ts index 14cb4d3..7ba5ab9 100644 --- a/packages/vike-solid/types/PageContext.ts +++ b/packages/vike-solid/types/PageContext.ts @@ -1,5 +1,5 @@ import type { JSX } from "solid-js"; -import type { ConfigFromHookResolved } from "./Config"; +import type { ConfigFromHookResolved, Stream } from "./Config"; // https://vike.dev/pageContext#typescript declare global { @@ -15,4 +15,5 @@ declare global { export type PageContextInternal = { _configFromHook?: ConfigFromHookResolved; _headAlreadySet?: boolean; + _stream?: Stream; };