~james/core

core/web/src/lib/ssr/worker.ts -rw-r--r-- 1.6 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 16 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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<string> => {
	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);
}