126 lines
3.8 KiB
TypeScript
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
|
|
},
|
|
}
|
|
})
|