import { createRequire } from "node:module"; import { fileURLToPath, URL } from "node:url"; import vue from "@vitejs/plugin-vue"; import { visualizer } from "rollup-plugin-visualizer"; import { defineConfig, loadEnv, type PluginOption } from "vite"; import { compression } from "vite-plugin-compression2"; const r = (path: string) => fileURLToPath(new URL(path, import.meta.url)); const nodeRequire = createRequire(import.meta.url); const resolveNodeModule = (specifier: string) => nodeRequire.resolve(specifier); export default defineConfig(({ mode }) => { const env = loadEnv(mode, ".", ""); const isProd = mode === "production"; const analyze = env.ANALYZE === "true"; const plugins: PluginOption[] = [vue()]; if (isProd) { plugins.push( compression({ algorithms: ["gzip", "brotliCompress"], threshold: 1024, }), ); } if (analyze) { plugins.push( visualizer({ filename: "stats.html", template: "treemap", gzipSize: true, brotliSize: true, open: true, }) as PluginOption, ); } return { plugins, resolve: { alias: { "@": r("./src"), "@geo/shared-types": r("../../packages/shared-types/src/index.ts"), "@geo/http-client": r("../../packages/http-client/src/index.ts"), "@jsquash/webp/encode.js": resolveNodeModule("@jsquash/webp/encode.js"), "@jsquash/webp/codec/enc/webp_enc.wasm": resolveNodeModule("@jsquash/webp/codec/enc/webp_enc.wasm"), "@jsquash/webp/codec/enc/webp_enc_simd.wasm": resolveNodeModule("@jsquash/webp/codec/enc/webp_enc_simd.wasm"), }, }, server: { host: "0.0.0.0", port: 5173, proxy: { "/api": { target: env.VITE_API_PROXY_TARGET || "http://localhost:8080", changeOrigin: true, }, "/swagger": { target: env.VITE_API_PROXY_TARGET || "http://localhost:8080", changeOrigin: true, }, }, }, esbuild: isProd ? { drop: ["console", "debugger"] } : undefined, build: { target: "es2022", sourcemap: "hidden", cssCodeSplit: true, assetsInlineLimit: 4096, chunkSizeWarningLimit: 800, reportCompressedSize: false, modulePreload: { polyfill: false }, rollupOptions: { output: { entryFileNames: "assets/js/[name]-[hash].js", chunkFileNames: "assets/js/[name]-[hash].js", assetFileNames: (info) => { const name = info.names?.[0] ?? ""; if (/\.(png|jpe?g|gif|svg|webp|avif|ico)$/i.test(name)) { return "assets/img/[name]-[hash][extname]"; } if (/\.(woff2?|eot|ttf|otf)$/i.test(name)) { return "assets/fonts/[name]-[hash][extname]"; } if (/\.css$/i.test(name)) { return "assets/css/[name]-[hash][extname]"; } return "assets/[name]-[hash][extname]"; }, manualChunks(id) { if (!id.includes("node_modules")) return undefined; // Milkdown editor and its heavy companion deps (only the editor route // imports them, so this chunk stays lazy-loaded). if ( id.includes("/@milkdown/") || id.includes("/prosemirror-") || id.includes("/@codemirror/") || id.includes("/@lezer/") || id.includes("/katex/") || id.includes("/micromark") || id.includes("/mdast-util") || id.includes("/hast-util") || id.includes("/unified/") || id.includes("/remark") || id.includes("/rehype") ) { return "milkdown"; } if ( id.includes("/ant-design-vue/") || id.includes("/@ant-design/") ) { return "antd"; } if (id.includes("/@tanstack/") || id.includes("/@vueuse/")) { return "query"; } if (id.includes("/@jsquash/")) { return "imaging"; } if (id.includes("/lodash") || id.includes("/dayjs")) { return "utils"; } if ( id.includes("/markdown-it") || id.includes("/dompurify") || id.includes("/entities/") ) { return "editor-utils"; } if ( id.includes("/vue/") || id.includes("/@vue/") || id.includes("/vue-router/") || id.includes("/vue-i18n/") || id.includes("/@intlify/") || id.includes("/pinia/") ) { return "vue-vendor"; } return "vendor"; }, }, }, }, }; });