import { isMainThread, parentPort, workerData } from "node:worker_threads"; import { getBlobUrl, setBlobUrl } from "#lib/markup/paths.ts"; import { renderMarkup } from "#lib/markup/render.ts"; import type { RenderTask } from "#lib/ssr/render.ts"; export const WORKER_ROLE = "tangled-ssr-render"; // dynamic import in pool.ts gives this module its own chunk url in both dev and build export const workerUrl = import.meta.url; const runTask = async (task: RenderTask): Promise => { if (task.kind === "markup") return renderMarkup(task.source, task.ctx); await import("#lib/syntax.ts"); const { preloadFile } = await import("@pierre/diffs/ssr"); const { prerenderedHTML } = await preloadFile({ file: { name: task.name, contents: task.contents }, options: task.options }); return prerenderedHTML; }; export type WorkerMessage = { ready: true } | { id: number; html: string } | { id: number; error: string }; export interface WorkerInit { role: typeof WORKER_ROLE; blobUrl: string; } export const workerInit = (): WorkerInit => ({ role: WORKER_ROLE, blobUrl: getBlobUrl() }); const init = workerData as WorkerInit | undefined; if (!isMainThread && parentPort && init?.role === WORKER_ROLE) { const port = parentPort; setBlobUrl(init.blobUrl); port.on("message", ({ id, task }: { id: number; task: RenderTask }) => { runTask(task).then( (html) => port.postMessage({ id, html } satisfies WorkerMessage), (cause: unknown) => port.postMessage({ id, error: String(cause) } satisfies WorkerMessage) ); }); port.postMessage({ ready: true } satisfies WorkerMessage); }