Lumen/vite.config.ts

80 lines
2.6 KiB
TypeScript

import { defineConfig, type Plugin } from "vite";
import { readdirSync, readFileSync, writeFileSync, existsSync } from "node:fs";
import { join } from "node:path";
import { execSync } from "node:child_process";
function lumenShellPlugin(): Plugin {
return {
name: "lumen-shell-precache",
closeBundle() {
const dist = "dist";
const swPath = join(dist, "sw.js");
if (!existsSync(swPath)) return;
// Deterministic version: package version + short git hash (if available)
let gitHash = "dev";
try {
gitHash = execSync("git rev-parse --short=8 HEAD", { stdio: ["ignore", "pipe", "ignore"] })
.toString()
.trim();
} catch {
// ignore
}
const pkg = JSON.parse(readFileSync("package.json", "utf8")) as { version: string };
const version = `${pkg.version}-${gitHash}`;
const cacheName = `lumen-shell-${version}`;
// Collect hashed assets produced by this build — sourcemaps excluded:
// they bloat the install (~580KB) and the SW would cache-first them.
const assetsDir = join(dist, "assets");
const assetFiles = existsSync(assetsDir) ? readdirSync(assetsDir) : [];
const hashedAssets = assetFiles.filter((f) => !f.endsWith(".map")).map((f) => `/assets/${f}`);
// Core shell URLs that must be precached (deterministic list per build)
const core = [
"/",
"/index.html",
"/fallback.html",
"/manifest.webmanifest",
"/sol_lunar_icon.svg",
"/icon.png",
"/icon-192.png",
"/icon-512.png",
];
const precache = [...core, ...hashedAssets];
let sw = readFileSync(swPath, "utf8");
sw = sw.replace(/const CACHE_NAME = "lumen-shell-v1";/, `const CACHE_NAME = "${cacheName}";`);
sw = sw.replace(
/const PRECACHE_URLS = \[[\s\S]*?\];/,
`const PRECACHE_URLS = ${JSON.stringify(precache, null, 2)};`,
);
// Also write precache manifest for debugging / future SW tooling
const manifestPath = join(dist, "precache-manifest.json");
writeFileSync(manifestPath, JSON.stringify({ cacheName, precache }, null, 2));
writeFileSync(swPath, sw);
},
};
}
export default defineConfig({
appType: "spa",
server: {
port: 5173,
strictPort: true,
},
plugins: [lumenShellPlugin()],
build: {
outDir: "dist",
assetsDir: "assets",
cssCodeSplit: false,
sourcemap: true,
rollupOptions: {
output: {
entryFileNames: "assets/[name]-[hash].js",
chunkFileNames: "assets/[name]-[hash].js",
assetFileNames: "assets/[name]-[hash].[ext]",
},
},
},
});