UNPKG

@tanstack/vue-router

Version:

Modern and scalable routing for Vue applications

52 lines (51 loc) 1.9 kB
import * as Vue from "vue"; import { transformReadableStreamWithRouter } from "@tanstack/router-core/ssr/server"; import { pipeToWebWritable, renderToString } from "vue/server-renderer"; import { ReadableStream } from "node:stream/web"; import { isbot } from "isbot"; //#region src/ssr/renderRouterToStream.tsx function prependDoctype(readable) { const encoder = new TextEncoder(); let sentDoctype = false; return new ReadableStream({ start(controller) { const reader = readable.getReader(); async function pump() { const { done, value } = await reader.read(); if (done) { controller.close(); return; } if (!sentDoctype) { sentDoctype = true; controller.enqueue(encoder.encode("<!DOCTYPE html>")); } controller.enqueue(value); return pump(); } pump().catch((err) => controller.error(err)); } }); } var renderRouterToStream = async ({ request, router, responseHeaders, App }) => { const app = Vue.createSSRApp(App, { router }); if (isbot(request.headers.get("User-Agent"))) { let fullHtml = await renderToString(app); const htmlOpenIndex = fullHtml.indexOf("<html"); const htmlCloseIndex = fullHtml.indexOf("</html>"); if (htmlOpenIndex !== -1 && htmlCloseIndex !== -1) fullHtml = fullHtml.slice(htmlOpenIndex, htmlCloseIndex + 7); else if (htmlOpenIndex !== -1) fullHtml = fullHtml.slice(htmlOpenIndex); return new Response(`<!DOCTYPE html>${fullHtml}`, { status: router.stores.statusCode.get(), headers: responseHeaders }); } const { writable, readable } = new TransformStream(); pipeToWebWritable(app, {}, writable); const responseStream = transformReadableStreamWithRouter(router, prependDoctype(readable)); return new Response(responseStream, { status: router.stores.statusCode.get(), headers: responseHeaders }); }; //#endregion export { renderRouterToStream }; //# sourceMappingURL=renderRouterToStream.js.map