frontend/vite.config.ts
2026-05-22 11:09:18 -06:00

126 lines
3.8 KiB
TypeScript

import { defineConfig, type Plugin, type UserConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'
import { VitePWA } from 'vite-plugin-pwa';
import * as path from 'path' // ✅ Import path module
import { readFileSync, renameSync, existsSync, unlinkSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { execSync } from 'node:child_process'
const rootDir = path.dirname(fileURLToPath(import.meta.url))
const LOCALNET_MODE = 'localnet'
/** Dev server: serve the minimal LAN shell (indexLocal.html) instead of the full index with third-party bootstraps. */
function useLocalnetShellHtml (mode: string, command: string): Plugin {
if (mode !== LOCALNET_MODE || command !== 'serve') {
return { name: 'localnet-shell-html-noop' }
}
return {
name: 'localnet-shell-html',
apply: 'serve',
transformIndexHtml: {
order: 'pre',
handler () {
return readFileSync(path.join(rootDir, 'indexLocal.html'), 'utf-8')
},
},
}
}
/** After build, LAN shell is emitted as indexLocal.html; rename to index.html so nginx and PWA still use /. */
function emitLocalnetShellAsIndexHtml (mode: string): Plugin {
if (mode !== LOCALNET_MODE) {
return { name: 'emit-localnet-shell-as-index-noop' }
}
return {
name: 'emit-localnet-shell-as-index-html',
closeBundle () {
const outDir = path.join(rootDir, 'build')
const from = path.join(outDir, 'indexLocal.html')
const to = path.join(outDir, 'index.html')
if (existsSync(from)) {
if (existsSync(to)) unlinkSync(to)
renameSync(from, to)
}
},
}
}
// https://vitejs.dev/config/
export default defineConfig(({ command, mode }): UserConfig => {
const useLocalnetShell = mode === LOCALNET_MODE
let gitHash = 'unknown'
try {
gitHash = execSync('git rev-parse --short HEAD').toString().trim()
} catch {}
const buildDate = new Date().toISOString()
return {
define: {
__BUILD_DATE__: JSON.stringify(buildDate),
__GIT_HASH__: JSON.stringify(gitHash),
},
plugins: [
useLocalnetShellHtml(mode, command),
emitLocalnetShellAsIndexHtml(mode),
react(),
tsconfigPaths(),
VitePWA({
registerType: 'autoUpdate', // Automatically updates the service worker when a new version is available
workbox: {
skipWaiting: true, //makes the new worker call skip waiting
clientsClaim: true, //makes it claim control of clients as soon as it activates
globPatterns: ['**/*.{js,css,html,png,jpg,svg}'], // Cache all common asset types
maximumFileSizeToCacheInBytes: 20 * 1024 * 1024, // 20 MiB
cleanupOutdatedCaches: true,
navigateFallback: "/index.html",
runtimeCaching: [
{
urlPattern: ({ request }) => request.destination === 'document',
handler: 'NetworkFirst',
options: {
cacheName: 'html-cache',
},
},
{
urlPattern: ({ request }) =>
['style', 'script', 'worker'].includes(request.destination),
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'assets-cache',
},
},
{
//this forces all api calls to go through the network
urlPattern: ({ url }) => url.pathname.startsWith('/v1/'),
handler: 'NetworkOnly',
options: {
cacheName: 'api-cache',
},
},
]
},
}),
],
build: {
outDir: './build',
sourcemap: true,
minify: false,
target: 'esnext',
rollupOptions: {
input: {
main: path.join(
rootDir,
useLocalnetShell ? 'indexLocal.html' : 'index.html'
),
},
}
},
esbuild: {
keepNames: true, // Prevent function name mangling
},
}
})