- Workbox: skipWaiting, clientsClaim, cleanupOutdatedCaches - NetworkFirst for navigations so HTML shell updates after deploy - deploy-site: cmp index.html vs SITE_ROOT; print nginx root hints; SW tips Made-with: Cursor
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
import { defineConfig } from 'vite';
|
|
import react from '@vitejs/plugin-react';
|
|
import { VitePWA } from 'vite-plugin-pwa';
|
|
import CONFIG from './gitprofile.config';
|
|
import { createHtmlPlugin } from 'vite-plugin-html';
|
|
|
|
// https://vitejs.dev/config/
|
|
export default defineConfig({
|
|
base: CONFIG.base || '/',
|
|
plugins: [
|
|
react(),
|
|
createHtmlPlugin({
|
|
inject: {
|
|
data: {
|
|
metaTitle: CONFIG.seo.title,
|
|
metaDescription: CONFIG.seo.description,
|
|
metaImageURL: CONFIG.seo.imageURL,
|
|
googleAnalyticsScript: CONFIG.googleAnalytics.id
|
|
? `<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=${CONFIG.googleAnalytics.id}"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
gtag('config', '${CONFIG.googleAnalytics.id}');
|
|
</script>`
|
|
: '',
|
|
},
|
|
},
|
|
}),
|
|
...(CONFIG.enablePWA
|
|
? [
|
|
VitePWA({
|
|
registerType: 'autoUpdate',
|
|
workbox: {
|
|
// Ship new SW immediately so deploys are not stuck behind the old cache.
|
|
skipWaiting: true,
|
|
clientsClaim: true,
|
|
cleanupOutdatedCaches: true,
|
|
// Omitting navigateFallback can still let some hosts/SW setups treat PDF
|
|
// navigations like SPA routes; denylist keeps real files out of the fallback.
|
|
navigateFallback: 'index.html',
|
|
navigateFallbackDenylist: [/\.pdf$/i],
|
|
// Large binaries in precache inflate Workbox memory during `vite build` on small VPSs.
|
|
globIgnores: ['**/*.pdf'],
|
|
runtimeCaching: [
|
|
{
|
|
urlPattern: ({ request }) => request.mode === 'navigate',
|
|
handler: 'NetworkFirst',
|
|
options: {
|
|
cacheName: 'pages',
|
|
networkTimeoutSeconds: 3,
|
|
expiration: { maxEntries: 32, maxAgeSeconds: 24 * 60 * 60 },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
// resume.pdf: serve from /resume.pdf; do not precache (cache quota + build RAM).
|
|
includeAssets: ['logo.png'],
|
|
manifest: {
|
|
name: 'Portfolio',
|
|
short_name: 'Portfolio',
|
|
description: 'Personal Portfolio',
|
|
icons: [
|
|
{
|
|
src: 'logo.png',
|
|
sizes: '64x64 32x32 24x24 16x16 192x192 512x512',
|
|
type: 'image/png',
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
]
|
|
: []),
|
|
],
|
|
define: {
|
|
CONFIG: CONFIG,
|
|
},
|
|
});
|