import { defineConfig, loadEnv } from "vite"; import solid from "vite-plugin-solid"; import solidStyled from "vite-plugin-solid-styled"; import suid from "@suid/vite-plugin"; import { VitePWA } from "vite-plugin-pwa"; import version from "vite-plugin-package-version"; import manifest from "./manifest.config"; import { GetManualChunk } from "rollup"; import devtools from "solid-devtools/vite"; import { resolve } from "node:path"; /** * Put all strings (/i18n/{key}.) into separated chunks based on the key. */ const chunkStrs: GetManualChunk = (id, { getModuleInfo }) => { const match = /.*\/i18n\/(.*)\.[jt]s.*$/.exec(id); if (match) { const key = match[1]; const dependentEntryPoints = []; // we use a Set here so we handle each module at most once. This // prevents infinite loops in case of circular dependencies const idsToHandle = new Set(getModuleInfo(id)!.dynamicImporters); for (const moduleId of idsToHandle) { const { isEntry, dynamicImporters, importers } = getModuleInfo(moduleId)!; if (isEntry || dynamicImporters.length > 0) dependentEntryPoints.push(moduleId); // The Set iterator is intelligent enough to iterate over // elements that are added during iteration for (const importerId of importers) idsToHandle.add(importerId); } // If there is a unique entry, we put it into a chunk based on the // entry name if (dependentEntryPoints.length === 1) { return `${key}.${ dependentEntryPoints[0].split("/").slice(-1)[0].split(".")[0] }.strings`; } // For multiple entries, we put it into a "shared" chunk if (dependentEntryPoints.length > 1) { return `${key}.shared.strings`; } } }; const manualChunks: GetManualChunk = (id, meta) => { return chunkStrs(id, meta); }; export default defineConfig(({ mode }) => { const devConf = loadEnv(mode, import.meta.dirname, "DEV"); const serverHttpCertBase = devConf["DEV_SERVER_HTTP_CERT_BASE"]; const serverHttpCertPassword = devConf["DEV_SERVER_HTTP_CERT_PASS"]; const serverHttpCertKey = serverHttpCertBase ? `${serverHttpCertBase}.key` : undefined; const serverHttpCertCrt = serverHttpCertBase ? `${serverHttpCertBase}.crt` : undefined; const isTestBuild = ["development", "staging"].includes(mode); return { plugins: [ devtools({ autoname: true, locator: { targetIDE: (devConf["DEV_LOCATOR_EDITOR"] as | "vscode" | "atom" | "webstorm" | "vscode-insiders" | "") || undefined, componentLocation: true, jsxLocation: true, }, }), suid(), solid(), solidStyled({ filter: { include: "src/**/*.{tsx,jsx}", exclude: "node_modules/**/*.{ts,js,tsx,jsx}", }, }), VitePWA({ strategies: "injectManifest", registerType: "autoUpdate", devOptions: { enabled: true, }, srcDir: "src/serviceworker", filename: "main.ts", manifest: manifest, pwaAssets: { config: true, }, injectManifest: { globPatterns: ["**/*.{js,wasm,css,html,svg,png,ico}"], }, }), version(), ], resolve: { alias: { /* We don't allow directly acessing the source root, because this encourage cross referencing between different module and loose the isolation. (Cross referencing is still possible, we don't stop it in any technical way.) If the module is so important and is being referencing everywhere in the app. Consider promoting it to the top dir. see docs/devnotes.md#module-isolation for details. */ "~platform": resolve(__dirname, "src/platform"), "~material": resolve(__dirname, "src/material"), }, }, server: { https: serverHttpCertBase ? { // This config controls https for the *dev server*. // See docs/dev-https.md for setting up https key: serverHttpCertKey, cert: serverHttpCertCrt, passphrase: serverHttpCertPassword, } : undefined, }, esbuild: { pure: isTestBuild ? undefined : ["console.debug", "console.trace"], drop: isTestBuild ? undefined : ["debugger"], }, define: { "import.meta.env.BUILT_AT": `"${new Date().toISOString()}"`, }, css: { devSourcemap: true, }, build: { target: ["firefox98", "safari15.4", "ios15.4", "chrome84", "edge87"], sourcemap: true, rollupOptions: { output: { manualChunks, }, }, }, }; });