diff --git a/index.html b/index.html
index a72a7b0c2..c6a0f11d1 100644
--- a/index.html
+++ b/index.html
@@ -58,6 +58,9 @@
window.GIT_COMMIT = <%- gitCommit %>;
window.INSTANCE_ID = <%- instanceId %>;
window.ASSET_MANIFEST = <%- assetManifest %>;
+ window.BOOTSTRAP_CONFIG = {
+ gameEnv: <%- gameEnv %>,
+ };
document.documentElement.style.setProperty(
"--background-image-url",
`url("<%- backgroundImageUrl %>")`,
diff --git a/src/core/configuration/ConfigLoader.ts b/src/core/configuration/ConfigLoader.ts
index 15771873b..0b8c79c8a 100644
--- a/src/core/configuration/ConfigLoader.ts
+++ b/src/core/configuration/ConfigLoader.ts
@@ -9,6 +9,14 @@ import { prodConfig } from "./ProdConfig";
export let cachedSC: ServerConfig | null = null;
+declare global {
+ interface Window {
+ BOOTSTRAP_CONFIG?: {
+ gameEnv?: string;
+ };
+ }
+}
+
export async function getConfig(
gameConfig: GameConfig,
userSettings: UserSettings | null,
@@ -30,16 +38,20 @@ export async function getServerConfigFromClient(): Promise {
if (cachedSC) {
return cachedSC;
}
- const response = await fetch("/api/env");
+ const bootstrapGameEnv = window.BOOTSTRAP_CONFIG?.gameEnv;
+ if (bootstrapGameEnv) {
+ cachedSC = getServerConfig(bootstrapGameEnv);
+ return cachedSC;
+ }
+
+ const response = await fetch("/api/env");
if (!response.ok) {
throw new Error(
`Failed to fetch server config: ${response.status} ${response.statusText}`,
);
}
const config = await response.json();
- // Log the retrieved configuration
- console.log("Server config loaded:", config);
cachedSC = getServerConfig(config.game_env);
return cachedSC;
@@ -63,3 +75,7 @@ export function getServerConfig(gameEnv: string) {
throw Error(`unsupported server configuration: ${gameEnv}`);
}
}
+
+export function clearCachedServerConfig(): void {
+ cachedSC = null;
+}
diff --git a/src/server/RenderHtml.ts b/src/server/RenderHtml.ts
index 2b2b3db17..9c31b2721 100644
--- a/src/server/RenderHtml.ts
+++ b/src/server/RenderHtml.ts
@@ -11,6 +11,7 @@ export async function renderHtmlContent(htmlPath: string): Promise {
gitCommit: JSON.stringify(process.env.GIT_COMMIT ?? "undefined"),
instanceId: JSON.stringify(process.env.INSTANCE_ID ?? "undefined"),
assetManifest: JSON.stringify(assetManifest),
+ gameEnv: JSON.stringify(process.env.GAME_ENV ?? "dev"),
manifestHref: buildAssetUrl("manifest.json", assetManifest),
faviconHref: buildAssetUrl("images/Favicon.svg", assetManifest),
gameplayScreenshotUrl: buildAssetUrl(
diff --git a/tests/core/configuration/ConfigLoader.test.ts b/tests/core/configuration/ConfigLoader.test.ts
new file mode 100644
index 000000000..65fd81757
--- /dev/null
+++ b/tests/core/configuration/ConfigLoader.test.ts
@@ -0,0 +1,24 @@
+import { beforeEach, describe, expect, test, vi } from "vitest";
+import { GameEnv } from "../../../src/core/configuration/Config";
+import {
+ clearCachedServerConfig,
+ getServerConfigFromClient,
+} from "../../../src/core/configuration/ConfigLoader";
+
+describe("ConfigLoader", () => {
+ beforeEach(() => {
+ vi.restoreAllMocks();
+ window.BOOTSTRAP_CONFIG = undefined;
+ clearCachedServerConfig();
+ });
+
+ test("uses bootstrap config without fetching /api/env", async () => {
+ window.BOOTSTRAP_CONFIG = { gameEnv: "prod" };
+ const fetchSpy = vi.spyOn(globalThis, "fetch");
+
+ const config = await getServerConfigFromClient();
+
+ expect(config.env()).toBe(GameEnv.Prod);
+ expect(fetchSpy).not.toHaveBeenCalled();
+ });
+});
diff --git a/vite.config.ts b/vite.config.ts
index 5fa1b9912..eefc073c2 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -27,6 +27,7 @@ export default defineConfig(({ mode }) => {
: {};
const htmlAssetData = {
assetManifest: JSON.stringify(assetManifest),
+ gameEnv: JSON.stringify(env.GAME_ENV ?? "dev"),
manifestHref: buildAssetUrl("manifest.json", assetManifest),
faviconHref: buildAssetUrl("images/Favicon.svg", assetManifest),
gameplayScreenshotUrl: buildAssetUrl(