80 lines
2.6 KiB
TypeScript
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]",
|
|
},
|
|
},
|
|
},
|
|
});
|