From 711742cae563fc888b064b8377a4c6a84d0b042d Mon Sep 17 00:00:00 2001 From: Muhammad Date: Sat, 7 Sep 2024 00:04:47 +0700 Subject: [PATCH] feat: add support for checking crawlers/bots and integrate `renderToStringAsync()` - Implemented detection for crawlers and bots - Updated rendering process to use `renderToStringAsync()` when accessed by crawlers/bots for improved SEO --- .../vike-solid/integration/onRenderHtml.tsx | 17 +++++++++++++---- packages/vike-solid/package.json | 1 + packages/vike-solid/types/isBot.d.ts | 4 ++++ pnpm-lock.yaml | 9 +++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 packages/vike-solid/types/isBot.d.ts diff --git a/packages/vike-solid/integration/onRenderHtml.tsx b/packages/vike-solid/integration/onRenderHtml.tsx index 79c907a..10fe525 100644 --- a/packages/vike-solid/integration/onRenderHtml.tsx +++ b/packages/vike-solid/integration/onRenderHtml.tsx @@ -1,5 +1,5 @@ // https://vike.dev/onRenderHtml -import { generateHydrationScript, renderToStream, renderToString } from "solid-js/web"; +import { generateHydrationScript, renderToStream, renderToString, renderToStringAsync } from "solid-js/web"; import { dangerouslySkipEscape, escapeInject, stampPipe } from "vike/server"; import { getHeadSetting } from "./getHeadSetting.js"; import { getPageElement } from "./getPageElement.js"; @@ -10,6 +10,7 @@ import type { PageContextInternal } from "../types/PageContext.js"; import type { Head } from "../types/Config.js"; import type { JSX } from "solid-js/jsx-runtime"; import { isCallable } from "../utils/isCallable.js"; +import isBot from "isbot-fast"; export { onRenderHtml }; @@ -18,7 +19,7 @@ type TPipe = Parameters[0]; const onRenderHtml: OnRenderHtmlAsync = async ( pageContext: PageContextServer & PageContextInternal, ): ReturnType => { - const pageHtml = getPageHtml(pageContext); + const pageHtml = await getPageHtml(pageContext); const headHtml = getHeadHtml(pageContext); @@ -40,10 +41,18 @@ const onRenderHtml: OnRenderHtmlAsync = async ( `; }; -function getPageHtml(pageContext: PageContextServer & PageContextInternal) { +async function getPageHtml(pageContext: PageContextServer & PageContextInternal) { let pageHtml: string | ReturnType | TPipe = ""; + const userAgent: string | undefined = + pageContext.headers?.["user-agent"] || + // TODO/eventually: remove old way of acccessing the User Agent header. + // @ts-ignore + pageContext.userAgent; + if (pageContext.Page) { - if (!pageContext.config.stream) { + if (userAgent && isBot(userAgent)) { + pageHtml = dangerouslySkipEscape(await renderToStringAsync(() => getPageElement(pageContext))); + } else if (!pageContext.config.stream) { pageHtml = dangerouslySkipEscape(renderToString(() => getPageElement(pageContext))); } else if (pageContext.config.stream === "web") { pageHtml = renderToStream(() => getPageElement(pageContext), { diff --git a/packages/vike-solid/package.json b/packages/vike-solid/package.json index f57e9c1..9e00a92 100644 --- a/packages/vike-solid/package.json +++ b/packages/vike-solid/package.json @@ -11,6 +11,7 @@ "release:commit": "LANG=en_US release-me commit" }, "dependencies": { + "isbot-fast": "^1.2.0", "vite-plugin-solid": "^2.10.2" }, "peerDependencies": { diff --git a/packages/vike-solid/types/isBot.d.ts b/packages/vike-solid/types/isBot.d.ts new file mode 100644 index 0000000..6cae9c1 --- /dev/null +++ b/packages/vike-solid/types/isBot.d.ts @@ -0,0 +1,4 @@ +declare module "isbot-fast" { + function isBot(userAgent: string): boolean; + export = isBot; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7676aac..3520e8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -95,6 +95,9 @@ importers: packages/vike-solid: dependencies: + isbot-fast: + specifier: ^1.2.0 + version: 1.2.0 vite-plugin-solid: specifier: ^2.10.2 version: 2.10.2(solid-js@1.8.22)(vite@5.4.2(@types/node@22.4.0)(terser@5.31.6)) @@ -1906,6 +1909,10 @@ packages: resolution: {integrity: sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==} engines: {node: '>=12.13'} + isbot-fast@1.2.0: + resolution: {integrity: sha512-twjuQzy2gKMDVfKGQyQqrx6Uy4opu/fiVUTTpdqtFsd7OQijIp5oXvb27n5EemYXaijh5fomndJt/SPRLsEdSg==} + engines: {node: '>=6.0.0'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -4490,6 +4497,8 @@ snapshots: is-what@4.1.15: {} + isbot-fast@1.2.0: {} + isexe@2.0.0: {} jackspeak@3.4.3: