Files
dusuniot/scripts/prod-server.ts
T

46 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* # 脚本 生产环境入口
* 包装 dist/server/server.js(TanStack Start 的 fetch handler):
* 先用 dist/client 的静态文件(构建产物 JS/CSS 等)直接应答,未命中的请求
* 交给 Start handler。没有这层包装时 /assets/* 会被路由 307 加尾斜杠后 404,
* 页面完全无 JS(水合不运行)。
*/
// 构建产物无类型声明(产物哈希文件名随构建变化)
// @ts-expect-error 构建产物无 d.ts
import serverEntry from "../dist/server/server.js";
import { readdirSync } from "node:fs";
/** # 成员变量 dist/client 静态文件表(pathname → 绝对路径,启动时递归扫描一次) **/
const CLIENT_DIR = new URL("../dist/client/", import.meta.url).pathname;
const staticFiles = new Map<string, string>();
/** # 函数 递归收集 dist/client 下全部静态文件 */
function walk(dir: string): void {
for (const e of readdirSync(dir, { withFileTypes: true })) {
const p = dir + "/" + e.name;
if (e.isDirectory()) walk(p);
// 归一化 key:物理路径去掉 CLIENT_DIR 前缀(可能残留多余斜杠)后补单斜杠
else staticFiles.set("/" + p.slice(CLIENT_DIR.length).replace(/^\/+/, ""), p);
}
}
walk(CLIENT_DIR);
export default {
/** # 成员变量 监听端口(PORT 环境变量可覆盖) **/
port: Number(process.env.PORT ?? 3312),
/** # 函数 请求入口:静态文件优先,其余交给 Start handler */
async fetch(req: Request): Promise<Response> {
const url = new URL(req.url);
// 尾斜杠归一化:偶发的 "<file>.jpg/" 形态请求(SPA 预取取回/上游转发)直接按静态
// 文件应答,避免交给 Start handler 后落入路由 catch-all 返回 404
let f = staticFiles.get(url.pathname);
if (!f && url.pathname.endsWith("/")) f = staticFiles.get(url.pathname.replace(/\/+$/, ""));
if (f) {
return new Response(Bun.file(f), {
headers: { "cache-control": "public, max-age=31536000, immutable" },
});
}
return serverEntry.fetch(req);
},
};