vite.config.ts (110 lines of code) (raw):

// eslint-disable-next-line @typescript-eslint/ban-ts-comment import vue from "@vitejs/plugin-vue" // @ts-ignore import path from "path" // @ts-ignore import { ComponentResolver } from "unplugin-vue-components" import Components from "unplugin-vue-components/vite" import { defineConfig, PluginOption } from "vite" // import visualizer from "rollup-plugin-visualizer" import { writeFile } from "fs/promises" import * as zlib from "zlib" import { OutputAsset, OutputChunk } from "rollup" import { configDefaults } from "vitest/config" import { viteStaticCopy } from "vite-plugin-static-copy" import { PrimeVueResolver } from "@primevue/auto-import-resolver" import tailwindcss from "@tailwindcss/vite" // https://vitejs.dev/config/ // noinspection SpellCheckingInspection,TypeScriptUnresolvedVariable export default defineConfig({ test: { root: "dashboard/new-dashboard", include: [...configDefaults.include, "**/*.{test,spec}.ts"], globals: true, environment: "jsdom", setupFiles: ["tests/setup.ts"], testTimeout: 10000, }, plugins: [ vue(), tailwindcss(), // visualizer({template: "sunburst"}), Components({ directoryAsNamespace: true, dts: path.resolve(__dirname, "dashboard/new-dashboard/src/components.d.ts"), resolvers: [ PrimeVueResolver(), // HeadlessUiResolver(), (name) => { // @ts-ignore const kind = process.env.NODE_ENV === "test" ? "" : "esm/" if (name.endsWith("Icon")) { return { path: `@heroicons/vue/24/outline/${kind}${name}.js`, } } else if (name.endsWith("IconSolid")) { return { path: `@heroicons/vue/20/solid/${kind}${name.substring(0, name.length - "Solid".length)}.js`, } } else { return null } }, ], }), brotli(), viteStaticCopy({ targets: [ { dest: "../../degradation-analyzer/kodata", src: path.resolve(__dirname, "dashboard/new-dashboard/resources/projects"), }, ], }), ], root: "dashboard/app", publicDir: path.resolve(__dirname, "dashboard/app/public"), server: { host: "localhost", port: 8080, }, build: { // sourcemap: true, reportCompressedSize: false, emptyOutDir: true, chunkSizeWarningLimit: 600, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore outDir: path.resolve(__dirname, "cmd/frontend/resources"), }, css: { preprocessorMaxWorkers: true, }, }) function brotli(): PluginOption { return { name: "offline-compression", writeBundle(outputOptions, bundle) { const outDir = outputOptions.dir! return Promise.all(Object.values(bundle).map((it) => brotliCompressFile(it, outDir))) as Promise<never> }, apply: "build", } } async function brotliCompressFile(asset: OutputAsset | OutputChunk, outDir: string): Promise<void> { const file = path.join(outDir, asset.fileName) // woff2 is based on the Brotli compression algorithm - no need to compress if (file.endsWith(".png") || file.endsWith(".woff2")) { return } const data = Buffer.from("code" in asset ? asset.code : (asset as OutputAsset).source) // https://github.com/google/ngx_brotli#brotli_min_length default is 20, so, we will compress any asset regardless of size if (data.length < 20) { throw new Error("Asset size is suspiciously small") } const mode = file.endsWith(".wasm") ? zlib.constants.BROTLI_MODE_GENERIC : zlib.constants.BROTLI_MODE_TEXT await new Promise((resolve, reject) => { zlib.brotliCompress( data, { params: { [zlib.constants.BROTLI_PARAM_MODE]: mode, [zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY, }, }, (error, buffer) => { if (error != null) { reject(error) return } writeFile(`${file}.br`, buffer).then(resolve, reject) } ) }) }