mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 16:46:38 +00:00
4aa726cfd8
## Description: Add an optional CDN_BASE env var that prefixes hashed asset URLs from asset-manifest.json, so the app can serve static assets from R2/CDN instead of the app origin. The value is determined at runtime via the EJS template (window.CDN_BASE) — empty string means "same origin," matching today's behavior. A hack to load the worker bundle: A same-origin Blob script that dynamic-import()s the cross-origin worker module and buffers early postMessage calls until the imported module's handler attaches, sidestepping the browser's refusal to construct a Worker directly from a cross-origin URL. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: evan
83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
import ejs from "ejs";
|
|
import type { Response } from "express";
|
|
import fs from "fs/promises";
|
|
import { buildAssetUrl } from "../core/AssetUrls";
|
|
import { setNoStoreHeaders } from "./NoStoreHeaders";
|
|
import { getRuntimeAssetManifest } from "./RuntimeAssetManifest";
|
|
|
|
const APP_SHELL_CACHE_CONTROL =
|
|
"public, max-age=0, s-maxage=300, stale-while-revalidate=86400";
|
|
|
|
const appShellContentCache = new Map<string, Promise<string>>();
|
|
|
|
export async function renderHtmlContent(htmlPath: string): Promise<string> {
|
|
const htmlContent = await fs.readFile(htmlPath, "utf-8");
|
|
const assetManifest = await getRuntimeAssetManifest();
|
|
const cdnBase = process.env.CDN_BASE ?? "";
|
|
return ejs.render(htmlContent, {
|
|
gitCommit: JSON.stringify(process.env.GIT_COMMIT ?? "undefined"),
|
|
assetManifest: JSON.stringify(assetManifest),
|
|
cdnBase: JSON.stringify(cdnBase),
|
|
// Raw (unquoted) value for use as a URL prefix in the index.html template,
|
|
// e.g. <script src="<%- cdnBaseRaw %>/assets/index-XXX.js">. The Vite
|
|
// build plugin inject-cdn-base-template rewrites Vite's emitted /assets/
|
|
// refs to use this placeholder.
|
|
cdnBaseRaw: cdnBase,
|
|
gameEnv: JSON.stringify(process.env.GAME_ENV ?? "dev"),
|
|
manifestHref: buildAssetUrl("manifest.json", assetManifest, cdnBase),
|
|
faviconHref: buildAssetUrl("images/Favicon.svg", assetManifest, cdnBase),
|
|
gameplayScreenshotUrl: buildAssetUrl(
|
|
"images/GameplayScreenshot.png",
|
|
assetManifest,
|
|
cdnBase,
|
|
),
|
|
backgroundImageUrl: buildAssetUrl(
|
|
"images/background.webp",
|
|
assetManifest,
|
|
cdnBase,
|
|
),
|
|
desktopLogoImageUrl: buildAssetUrl(
|
|
"images/OpenFront.png",
|
|
assetManifest,
|
|
cdnBase,
|
|
),
|
|
mobileLogoImageUrl: buildAssetUrl("images/OF.png", assetManifest, cdnBase),
|
|
});
|
|
}
|
|
|
|
export async function getAppShellContent(htmlPath: string): Promise<string> {
|
|
let cachedContent = appShellContentCache.get(htmlPath);
|
|
if (!cachedContent) {
|
|
cachedContent = renderHtmlContent(htmlPath).catch((error: unknown) => {
|
|
appShellContentCache.delete(htmlPath);
|
|
throw error;
|
|
});
|
|
appShellContentCache.set(htmlPath, cachedContent);
|
|
}
|
|
return cachedContent;
|
|
}
|
|
|
|
export function clearAppShellContentCache(): void {
|
|
appShellContentCache.clear();
|
|
}
|
|
|
|
export function setAppShellCacheHeaders(res: Response): void {
|
|
res.setHeader("Cache-Control", APP_SHELL_CACHE_CONTROL);
|
|
res.setHeader("Content-Type", "text/html");
|
|
}
|
|
|
|
export function setHtmlNoCacheHeaders(res: Response): void {
|
|
setNoStoreHeaders(res);
|
|
res.setHeader("ETag", "");
|
|
res.setHeader("Content-Type", "text/html");
|
|
}
|
|
|
|
export async function renderAppShell(
|
|
res: Response,
|
|
htmlPath: string,
|
|
): Promise<void> {
|
|
const rendered = await getAppShellContent(htmlPath);
|
|
setAppShellCacheHeaders(res);
|
|
res.send(rendered);
|
|
}
|