import fs from "fs" import { defineConfig } from "vite" import solid from "vite-plugin-solid" import { VitePWA } from "vite-plugin-pwa" import { resolve } from "path" import { copyMonacoPublicAssets } from "./scripts/monaco-public-assets.js" const uiPackageJson = JSON.parse(fs.readFileSync(resolve(__dirname, "package.json"), "utf-8")) as { version?: string } const uiVersion = uiPackageJson.version ?? "0.0.0" export default defineConfig({ root: "./src/renderer", plugins: [ solid(), { name: "prepare-monaco-public-assets", // Ensure Monaco's AMD assets exist in `root/public` for both dev server and builds. // These files are gitignored and generated on demand. configureServer(server) { copyMonacoPublicAssets({ uiRendererRoot: resolve(__dirname, "src/renderer"), warn: (msg) => server.config.logger.warn(msg), sourceRoots: [ resolve(__dirname, "../../node_modules/monaco-editor/min/vs"), resolve(__dirname, "node_modules/monaco-editor/min/vs"), ], }) }, buildStart() { copyMonacoPublicAssets({ uiRendererRoot: resolve(__dirname, "src/renderer"), warn: (msg) => this.warn(msg), sourceRoots: [ resolve(__dirname, "../../node_modules/monaco-editor/min/vs"), resolve(__dirname, "node_modules/monaco-editor/min/vs"), ], }) }, }, { name: "emit-ui-version", generateBundle() { this.emitFile({ type: "asset", fileName: "ui-version.json", source: JSON.stringify({ uiVersion }, null, 2), }) }, }, { name: "prepare-pwa-source-icon", apply: "build", buildStart() { // vite-pwa-assets requires the source image inside root/public/ const source = resolve(__dirname, "src/images/CodeNomad-Icon.png") const publicDir = resolve(__dirname, "src/renderer/public") const dest = resolve(publicDir, "logo.png") fs.mkdirSync(publicDir, { recursive: true }) fs.copyFileSync(source, dest) }, }, VitePWA({ registerType: "autoUpdate", injectRegister: "auto", pwaAssets: { preset: "minimal-2023", image: "public/logo.png", }, manifest: { name: "CodeNomad", short_name: "CodeNomad", id: "/", start_url: "/", display: "standalone", display_override: ["window-controls-overlay", "standalone"], background_color: "#1a1a1a", theme_color: "#1a1a1a", }, workbox: { // Workbox defaults to 2 MiB; our main bundle can slightly exceed that. // This is a build-time limit for the precache manifest, not a hard runtime cap. maximumFileSizeToCacheInBytes: 3 * 1024 * 1024, // Preserve server-side auth redirects (e.g., /login) instead of serving cached index.html. navigateFallback: null, // Only precache static assets (avoid caching HTML documents / routes). globPatterns: ["**/*.{js,css,png,jpg,jpeg,svg,webp,ico,woff,woff2,ttf,eot,json,webmanifest}"], // Monaco assets can be large; cache them at runtime instead. globIgnores: [ "**/*.html", "**/assets/*worker-*.js", "**/assets/editor.api-*.js", "**/monaco/vs/**/*", ], // Only cache static UI assets; never cache API traffic. runtimeCaching: [ { urlPattern: ({ url, request }) => { if (url.pathname.startsWith("/api/")) return false if (request.destination === "document") return false return ["script", "style", "image", "font"].includes(request.destination) }, handler: "CacheFirst", options: { cacheName: "asset-cache", expiration: { maxEntries: 200, maxAgeSeconds: 60 * 60 * 24 * 30 }, cacheableResponse: { statuses: [0, 200] }, }, }, ], }, }), ], css: { postcss: "./postcss.config.js", }, resolve: { alias: { "@": resolve(__dirname, "./src"), }, }, optimizeDeps: { exclude: ["lucide-solid"], }, ssr: { noExternal: ["lucide-solid"], }, server: { port: 3000, }, build: { outDir: "dist", rollupOptions: { input: { main: resolve(__dirname, "./src/renderer/index.html"), loading: resolve(__dirname, "./src/renderer/loading.html"), }, output: { manualChunks(id) { const normalizedId = id.replace(/\\/g, "/") if (normalizedId.includes("/node_modules/@git-diff-view/")) { return "git-diff-vendor" } if (normalizedId.includes("/node_modules/highlight.js/") || normalizedId.includes("/node_modules/lowlight/")) { return "highlight-vendor" } if (normalizedId.includes("/node_modules/fast-diff/")) { return "fast-diff-vendor" } if (normalizedId.includes("/node_modules/monaco-editor/")) { return "monaco-vendor" } if ( normalizedId.includes("/src/components/file-viewer/") || normalizedId.includes("/src/lib/monaco/") ) { return "monaco-viewer" } }, }, }, }, })