mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-01 20:13:24 +00:00
Add versioned asset URL infrastructure
This commit is contained in:
+7
-11
@@ -7,8 +7,8 @@
|
||||
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
<title data-i18n="main.title">OpenFront (ALPHA)</title>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="icon" type="image/svg+xml" href="/images/Favicon.svg" />
|
||||
<link rel="manifest" href="<%- manifestHref %>" />
|
||||
<link rel="icon" type="image/svg+xml" href="<%- faviconHref %>" />
|
||||
|
||||
<!-- Preload styles -->
|
||||
<style>
|
||||
@@ -50,16 +50,14 @@
|
||||
property="og:description"
|
||||
content="Conquer the world in this multiplayer battle royale! Expand your nation, eliminate opponents, and dominate the map in this fast-paced IO game."
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://openfront.io/images/GameplayScreenshot.png"
|
||||
/>
|
||||
<meta property="og:image" content="<%- gameplayScreenshotUrl %>" />
|
||||
<meta property="og:type" content="game" />
|
||||
|
||||
<!-- Injected from Server env -->
|
||||
<script>
|
||||
window.GIT_COMMIT = <%- gitCommit %>;
|
||||
window.INSTANCE_ID = <%- instanceId %>;
|
||||
window.ASSET_BASE_PATH = <%- assetBasePath %>;
|
||||
</script>
|
||||
|
||||
<!-- CrazyGames SDK -->
|
||||
@@ -126,21 +124,19 @@
|
||||
<div
|
||||
id="background-layer"
|
||||
class="absolute inset-0 bg-cover bg-center opacity-30 [filter:brightness(1.0)] dark:[filter:sepia(0.2)_saturate(1.2)_hue-rotate(180deg)_brightness(0.9)]"
|
||||
style="
|
||||
background-image: url("/resources/images/background.webp");
|
||||
"
|
||||
style="background-image: url("<%- backgroundImageUrl %>")"
|
||||
></div>
|
||||
<div
|
||||
class="absolute inset-0 bg-center bg-no-repeat bg-contain hidden lg:block"
|
||||
style="
|
||||
background-image: url("/resources/images/OpenFront.webp");
|
||||
background-image: url("<%- desktopLogoImageUrl %>");
|
||||
opacity: 0.5;
|
||||
"
|
||||
></div>
|
||||
<div
|
||||
class="absolute inset-0 bg-center bg-no-repeat bg-contain lg:hidden"
|
||||
style="
|
||||
background-image: url("/resources/images/OF.webp");
|
||||
background-image: url("<%- mobileLogoImageUrl %>");
|
||||
opacity: 0.5;
|
||||
"
|
||||
></div>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
export function normalizeAssetVersion(
|
||||
version: string | null | undefined,
|
||||
): string | null {
|
||||
const trimmed = version?.trim();
|
||||
if (!trimmed || trimmed === "DEV" || trimmed === "undefined") {
|
||||
return null;
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
export function buildVersionedAssetBasePath(
|
||||
version: string | null | undefined,
|
||||
): string {
|
||||
const normalized = normalizeAssetVersion(version);
|
||||
return normalized ? `/_assets/${encodeURIComponent(normalized)}` : "";
|
||||
}
|
||||
|
||||
export function buildAssetUrl(
|
||||
path: string,
|
||||
assetBasePath: string = "",
|
||||
): string {
|
||||
const normalizedPath = path.replace(/^\/+/, "");
|
||||
if (!assetBasePath) {
|
||||
return `/${normalizedPath}`;
|
||||
}
|
||||
return `${assetBasePath}/${normalizedPath}`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
var __ASSET_BASE_PATH__: string | undefined;
|
||||
|
||||
interface Window {
|
||||
ASSET_BASE_PATH?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export function getAssetBasePath(): string {
|
||||
if (typeof window !== "undefined" && window.ASSET_BASE_PATH !== undefined) {
|
||||
return window.ASSET_BASE_PATH;
|
||||
}
|
||||
return globalThis.__ASSET_BASE_PATH__ ?? "";
|
||||
}
|
||||
|
||||
export function assetUrl(path: string): string {
|
||||
return buildAssetUrl(path, getAssetBasePath());
|
||||
}
|
||||
@@ -1,12 +1,24 @@
|
||||
import ejs from "ejs";
|
||||
import type { Response } from "express";
|
||||
import fs from "fs/promises";
|
||||
import { buildAssetUrl, buildVersionedAssetBasePath } from "../core/AssetUrls";
|
||||
|
||||
export async function renderHtmlContent(htmlPath: string): Promise<string> {
|
||||
const htmlContent = await fs.readFile(htmlPath, "utf-8");
|
||||
const assetBasePath = buildVersionedAssetBasePath(process.env.GIT_COMMIT);
|
||||
return ejs.render(htmlContent, {
|
||||
gitCommit: JSON.stringify(process.env.GIT_COMMIT ?? "undefined"),
|
||||
instanceId: JSON.stringify(process.env.INSTANCE_ID ?? "undefined"),
|
||||
assetBasePath: JSON.stringify(assetBasePath),
|
||||
manifestHref: buildAssetUrl("manifest.json", assetBasePath),
|
||||
faviconHref: buildAssetUrl("images/Favicon.svg", assetBasePath),
|
||||
gameplayScreenshotUrl: buildAssetUrl(
|
||||
"images/GameplayScreenshot.png",
|
||||
assetBasePath,
|
||||
),
|
||||
backgroundImageUrl: buildAssetUrl("images/background.webp", assetBasePath),
|
||||
desktopLogoImageUrl: buildAssetUrl("images/OpenFront.webp", assetBasePath),
|
||||
mobileLogoImageUrl: buildAssetUrl("images/OF.webp", assetBasePath),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import { createHtmlPlugin } from "vite-plugin-html";
|
||||
import { viteStaticCopy } from "vite-plugin-static-copy";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import {
|
||||
buildAssetUrl,
|
||||
buildVersionedAssetBasePath,
|
||||
normalizeAssetVersion,
|
||||
} from "./src/core/AssetUrls";
|
||||
|
||||
// Vite already handles these, but its good practice to define them explicitly
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -13,6 +19,52 @@ const __dirname = path.dirname(__filename);
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), "");
|
||||
const isProduction = mode === "production";
|
||||
const assetVersion = normalizeAssetVersion(
|
||||
env.GIT_COMMIT ?? process.env.GIT_COMMIT,
|
||||
);
|
||||
const assetBasePath = buildVersionedAssetBasePath(assetVersion);
|
||||
const htmlAssetData = {
|
||||
assetBasePath: JSON.stringify(assetBasePath),
|
||||
manifestHref: buildAssetUrl("manifest.json", assetBasePath),
|
||||
faviconHref: buildAssetUrl("images/Favicon.svg", assetBasePath),
|
||||
gameplayScreenshotUrl: buildAssetUrl(
|
||||
"images/GameplayScreenshot.png",
|
||||
assetBasePath,
|
||||
),
|
||||
backgroundImageUrl: buildAssetUrl("images/background.webp", assetBasePath),
|
||||
desktopLogoImageUrl: buildAssetUrl("images/OpenFront.webp", assetBasePath),
|
||||
mobileLogoImageUrl: buildAssetUrl("images/OF.webp", assetBasePath),
|
||||
};
|
||||
|
||||
const rewriteVersionedManifest = () => ({
|
||||
name: "rewrite-versioned-manifest",
|
||||
apply: "build" as const,
|
||||
async closeBundle() {
|
||||
if (!assetVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
const manifestPath = path.join(
|
||||
__dirname,
|
||||
"static",
|
||||
"_assets",
|
||||
assetVersion,
|
||||
"manifest.json",
|
||||
);
|
||||
const manifest = JSON.parse(await fs.readFile(manifestPath, "utf8")) as {
|
||||
icons?: Array<{ src?: string }>;
|
||||
};
|
||||
manifest.icons = manifest.icons?.map((icon) => ({
|
||||
...icon,
|
||||
src: buildAssetUrl(icon.src ?? "", assetBasePath),
|
||||
}));
|
||||
await fs.writeFile(
|
||||
manifestPath,
|
||||
`${JSON.stringify(manifest, null, 2)}\n`,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// In dev, redirect visits to /w*/game/* to "/" so Vite serves the index.html.
|
||||
const devGameHtmlBypass = (req?: {
|
||||
url?: string;
|
||||
@@ -65,22 +117,33 @@ export default defineConfig(({ mode }) => {
|
||||
data: {
|
||||
gitCommit: JSON.stringify("DEV"),
|
||||
instanceId: JSON.stringify("DEV_ID"),
|
||||
...htmlAssetData,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
...(assetVersion
|
||||
? [
|
||||
{
|
||||
src: "resources/**/*",
|
||||
dest: `_assets/${assetVersion}`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
src: "proprietary/*",
|
||||
dest: ".",
|
||||
},
|
||||
],
|
||||
}),
|
||||
...(isProduction ? [rewriteVersionedManifest()] : []),
|
||||
tailwindcss(),
|
||||
],
|
||||
|
||||
define: {
|
||||
__ASSET_BASE_PATH__: JSON.stringify(assetBasePath),
|
||||
"process.env.WEBSOCKET_URL": JSON.stringify(
|
||||
isProduction ? "" : "localhost:3000",
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user