seia.js
Version:
Lightweight SSR framework for React Server Components
78 lines (77 loc) • 3.24 kB
JavaScript
/** @jsxImportSource hono/jsx */ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
import { serve as nodeServe } from '@hono/node-server';
import { serveStatic } from '@hono/node-server/serve-static';
import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { renderToReadableStream } from 'react-dom/server.edge';
import { makeBanner } from './banner.js';
import { renderRscPayloadStream, renderRscPayloadStreamToDom } from './renderer.js';
import { changeExtension } from './utils-path.js';
import { trimPrefix } from './utils.js';
const injectGlobal = (rscPayload)=>`globalThis.__SEIA_RSC_PAYLOAD = \`${rscPayload}\``;
/**
* Start Seia SSR server.
*/ export const serve = async (config)=>{
const { paths: { entry, dist, anchor }, serve: { port } } = config;
const app = new Hono();
app.use(logger());
app.use('/@seia/*', serveStatic({
root: dist,
rewriteRequestPath: (path)=>trimPrefix(path, '/@seia')
}));
app.get('/', async (c)=>{
const entryFile = changeExtension(entry, '.js') + '#' + anchor;
const [worker, stream] = await renderRscPayloadStream(entryFile, config);
const [rscPayloadStream, domStream] = stream.tee();
const rscPayload = await new Response(rscPayloadStream).text();
const dom = await renderRscPayloadStreamToDom(domStream, config);
const __html = await new Response(await renderToReadableStream(dom)).text();
await worker.terminate();
return c.html(/*#__PURE__*/ _jsxs("html", {
children: [
/*#__PURE__*/ _jsxs("head", {
children: [
/*#__PURE__*/ _jsx("meta", {
charSet: "utf-8"
}),
/*#__PURE__*/ _jsx("meta", {
name: "viewport",
content: "width=device-width, initial-scale=1.0"
}),
/*#__PURE__*/ _jsx("title", {
children: "Seia SSR"
}),
/*#__PURE__*/ _jsx("link", {
rel: "stylesheet",
href: "/@seia/style.css"
}),
/*#__PURE__*/ _jsx("script", {
type: "module",
src: "/@seia/client.js"
})
]
}),
/*#__PURE__*/ _jsxs("body", {
children: [
/*#__PURE__*/ _jsx("div", {
id: "root",
dangerouslySetInnerHTML: {
__html
}
}),
/*#__PURE__*/ _jsx("script", {
dangerouslySetInnerHTML: {
__html: injectGlobal(rscPayload)
}
})
]
})
]
}));
});
console.log(makeBanner(config));
nodeServe({
fetch: app.fetch,
port
});
};