import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { VitePWA } from "vite-plugin-pwa"; import { fileURLToPath } from "node:url"; const at = (p: string) => fileURLToPath(new URL(p, import.meta.url)); export default defineConfig({ // The app lives in app/, but lib/ and data/ sit at the repo root so // `node validate.mjs` keeps running against them verbatim. resolve: { alias: { "@lib": at("../lib"), "@data": at("../data"), "@app": at("./src"), "@shared": at("../shared"), "@prompt": at("../prompt"), }, }, server: { fs: { allow: [at("..")] }, }, worker: { format: "es" }, optimizeDeps: { // sqlite-wasm must not be pre-bundled; it loads its .wasm relative to // its own module URL and dep-optimising rewrites that path. exclude: ["@sqlite.org/sqlite-wasm"], }, build: { target: "es2022", // The dictionary band files are large and already gzipped at build time. assetsInlineLimit: 0, }, plugins: [ react(), VitePWA({ registerType: "autoUpdate", includeAssets: ["favicon.svg"], manifest: { name: "Hankan — 한국어 읽기", short_name: "Hankan", description: "A Korean reading tutor for manhwa. Works offline.", lang: "en", start_url: "/", display: "standalone", background_color: "#F1F4F1", theme_color: "#0F6B5C", icons: [ { src: "icon-192.png", sizes: "192x192", type: "image/png" }, { src: "icon-512.png", sizes: "512x512", type: "image/png" }, { src: "icon-512.png", sizes: "512x512", type: "image/png", purpose: "maskable", }, ], }, workbox: { // Offline is the whole point: everything the app needs, including the // dictionary band files and the wasm binary, is precached. globPatterns: ["**/*.{js,css,html,svg,png,woff2,wasm,gz,json}"], maximumFileSizeToCacheInBytes: 12 * 1024 * 1024, }, }), ], });