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, ws: 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('/@codemirror/') || id.includes('/@lezer/') || id.includes('/katex/') || id.includes('/micromark') || id.includes('/mdast-util') || id.includes('/unist-util') || id.includes('/hast-util') || id.includes('/unified/') || id.includes('/remark') || id.includes('/rehype') || id.includes('/decode-named-character-reference/') || id.includes('/vfile') || id.includes('/zwitch/') || id.includes('/longest-streak/') || id.includes('/bail/') || id.includes('/extend/') || id.includes('/devlop/') || id.includes('/is-plain-obj/') || id.includes('/trough/') || id.includes('/ccount/') || id.includes('/escape-string-regexp/') || id.includes('/markdown-table/') || id.includes('/@marijn/') || id.includes('/orderedmap/') || id.includes('/w3c-keyname/') || id.includes('/rope-sequence/') || id.includes('/style-mod/') || id.includes('/crelt/') || id.includes('/@floating-ui/') || id.includes('/clsx/') || id.includes('/@ocavue/') ) { return 'milkdown' } if (id.includes('/nanoid/')) { return 'nanoid' } 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('/jspdf/') || id.includes('/html2canvas/') || id.includes('/canvg/') || id.includes('/css-line-break/') || id.includes('/text-segmentation/') || id.includes('/fflate/') || id.includes('/pako/') || id.includes('/base64-arraybuffer/') || id.includes('/fast-png/') || id.includes('/iobuffer/') || id.includes('/raf/') || id.includes('/rgbcolor/') || id.includes('/stackblur-canvas/') || id.includes('/svg-pathdata/') || id.includes('/utrie/') ) { return 'pdf-export' } if ( id.includes('/docx/') || id.includes('/jszip/') || id.includes('/xml-js/') || id.includes('/xml/') || id.includes('/hash.js/') ) { return 'word-export' } if (id.includes('/lodash') || id.includes('/dayjs')) { return 'utils' } if ( id.includes('/markdown-it') || id.includes('/dompurify') || id.includes('/entities/') || id.includes('/mdurl/') || id.includes('/uc.micro/') || id.includes('/linkify-it/') || id.includes('/punycode.js/') ) { 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' }, }, }, }, } })