import type { Plugin } from "vite"; import { bootLeaks, type ChunkLike } from "./src/lib/chunkLeaks"; // A lazily imported page, rail, dialog or player must stay out of the chunks loaded at boot (the // entry, the shell and what they import): one static import of it on the boot path — a module's // index.ts re-exporting it is the easy way — makes its import() a silent no-op. That rule used to be // a hope; this makes it a build failure, naming each module and the boot chunk it landed in. const SHELL = "src/shell/App.tsx"; export function chunkGuard(): Plugin { return { name: "siftlode-chunk-guard", apply: "build", generateBundle(_options, bundle) { const lazy = new Set( [...this.getModuleIds()].filter( (id) => (this.getModuleInfo(id)?.dynamicImporters.length ?? 0) > 0, ), ); const chunks: ChunkLike[] = Object.values(bundle).flatMap((o) => o.type === "chunk" ? [ { fileName: o.fileName, isEntry: o.isEntry, imports: o.imports, moduleIds: o.moduleIds, }, ] : [], ); const leaks = bootLeaks(chunks, lazy, SHELL); if (leaks.length) this.error( `lazily imported, yet loaded at boot: ${leaks.join(", ")}. ` + "Something on the boot path imports it statically (an index.ts re-export?): import it lazily there too, or not at all.", ); }, }; }