From 2cafb71b7939c54ea85d0925890ab3a1d38ca606 Mon Sep 17 00:00:00 2001 From: scamiv <6170744+scamiv@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:21:09 +0100 Subject: [PATCH] Emit runtime asset manifest as ESM module --- src/server/PublicAssetManifest.ts | 10 +++++++--- src/server/RuntimeAssetManifest.ts | 22 +++++++++++++++------- vite.config.ts | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/server/PublicAssetManifest.ts b/src/server/PublicAssetManifest.ts index 9ddb065f0..34182132c 100644 --- a/src/server/PublicAssetManifest.ts +++ b/src/server/PublicAssetManifest.ts @@ -141,11 +141,15 @@ export function copyRootPublicFiles( } } -export function writePublicAssetManifestFile( +export function writePublicAssetManifestModule( outDir: string, assetManifest: AssetManifest, ): void { - const manifestPath = path.join(outDir, "_assets", "asset-manifest.json"); + const manifestPath = path.join(outDir, "_assets", "asset-manifest.mjs"); fs.mkdirSync(path.dirname(manifestPath), { recursive: true }); - fs.writeFileSync(manifestPath, `${JSON.stringify(assetManifest, null, 2)}\n`); + const serializedManifest = JSON.stringify(assetManifest, null, 2); + fs.writeFileSync( + manifestPath, + `const assetManifest = ${serializedManifest};\nexport { assetManifest };\nexport default assetManifest;\n`, + ); } diff --git a/src/server/RuntimeAssetManifest.ts b/src/server/RuntimeAssetManifest.ts index 812247889..3e4916ed8 100644 --- a/src/server/RuntimeAssetManifest.ts +++ b/src/server/RuntimeAssetManifest.ts @@ -1,18 +1,25 @@ -import fs from "fs/promises"; import path from "path"; -import { fileURLToPath } from "url"; +import { fileURLToPath, pathToFileURL } from "url"; import type { AssetManifest } from "../core/AssetUrls"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const staticDir = path.join(__dirname, "../../static"); -const manifestPath = path.join(staticDir, "_assets", "asset-manifest.json"); +const manifestPath = path.join(staticDir, "_assets", "asset-manifest.mjs"); let manifestPromise: Promise | null = null; +let manifestVersion = 0; -async function readRuntimeAssetManifest(): Promise { - const raw = await fs.readFile(manifestPath, "utf8"); - return JSON.parse(raw) as AssetManifest; +async function importRuntimeAssetManifest( + version: number, +): Promise { + const manifestModule = (await import( + `${pathToFileURL(manifestPath).href}?v=${version}` + )) as { + assetManifest?: AssetManifest; + default?: AssetManifest; + }; + return manifestModule.assetManifest ?? manifestModule.default ?? {}; } export async function getRuntimeAssetManifest(): Promise { @@ -20,10 +27,11 @@ export async function getRuntimeAssetManifest(): Promise { return {}; } - manifestPromise ??= readRuntimeAssetManifest(); + manifestPromise ??= importRuntimeAssetManifest(manifestVersion); return manifestPromise; } export function clearRuntimeAssetManifestCache(): void { + manifestVersion++; manifestPromise = null; } diff --git a/vite.config.ts b/vite.config.ts index 695a89aae..5fa1b9912 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -11,7 +11,7 @@ import { copyRootPublicFiles, createHashedPublicAssetFiles, getResourcesDir, - writePublicAssetManifestFile, + writePublicAssetManifestModule, } from "./src/server/PublicAssetManifest"; // Vite already handles these, but its good practice to define them explicitly @@ -44,7 +44,7 @@ export default defineConfig(({ mode }) => { closeBundle() { const outDir = path.join(__dirname, "static"); copyRootPublicFiles(resourcesDir, outDir); - writePublicAssetManifestFile(outDir, assetManifest); + writePublicAssetManifestModule(outDir, assetManifest); createHashedPublicAssetFiles(resourcesDir, outDir, assetManifest); }, });