You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.6 KiB
184 lines
5.6 KiB
import { sveltekit } from '@sveltejs/kit/vite'; |
|
import { defineConfig } from 'vite'; |
|
import { execSync } from 'child_process'; |
|
import { SvelteKitPWA } from '@vite-pwa/sveltekit'; |
|
import compression from 'vite-plugin-compression'; |
|
import { readFileSync } from 'fs'; |
|
import { join } from 'path'; |
|
|
|
// Read version from package.json for environment variable injection |
|
function getPackageVersion(): string { |
|
try { |
|
const packageJsonPath = join(process.cwd(), 'package.json'); |
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')); |
|
return packageJson.version || '0.3.2'; |
|
} catch { |
|
return '0.3.2'; |
|
} |
|
} |
|
|
|
export default defineConfig({ |
|
publicDir: 'static', |
|
define: { |
|
// Inject version from package.json at build time |
|
'import.meta.env.VITE_APP_VERSION': JSON.stringify(getPackageVersion()), |
|
}, |
|
plugins: [ |
|
sveltekit(), |
|
compression({ |
|
algorithm: 'gzip', |
|
ext: '.gz', |
|
threshold: 1024, // Compress files > 1KB |
|
}), |
|
compression({ |
|
algorithm: 'brotliCompress', |
|
ext: '.br', |
|
threshold: 1024, |
|
}), |
|
SvelteKitPWA({ |
|
strategies: 'generateSW', |
|
registerType: 'autoUpdate', |
|
workbox: { |
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff,woff2,webp,avif}'], |
|
maximumFileSizeToCacheInBytes: 3 * 1024 * 1024, // 3 MB to handle large chunks |
|
runtimeCaching: [ |
|
{ |
|
urlPattern: /^https:\/\/.*\.(?:png|jpg|jpeg|svg|gif|webp|avif)$/i, |
|
handler: 'CacheFirst', |
|
options: { |
|
cacheName: 'images-cache', |
|
expiration: { |
|
maxEntries: 200, |
|
maxAgeSeconds: 60 * 60 * 24 * 30 // 30 days |
|
} |
|
} |
|
}, |
|
{ |
|
// Cache API responses (relay responses) with cache-first strategy for slow connections |
|
urlPattern: /^wss?:\/\//i, |
|
handler: 'CacheFirst', |
|
options: { |
|
cacheName: 'api-cache', |
|
expiration: { |
|
maxEntries: 200, // Increased from 50 |
|
maxAgeSeconds: 60 * 60 * 24 // 24 hours instead of 5 minutes (optimized for slow connections) |
|
} |
|
} |
|
}, |
|
{ |
|
// Cache static assets with stale-while-revalidate for better performance |
|
urlPattern: /\.(?:js|css|woff|woff2)$/i, |
|
handler: 'StaleWhileRevalidate', |
|
options: { |
|
cacheName: 'static-assets', |
|
expiration: { |
|
maxEntries: 100, |
|
maxAgeSeconds: 60 * 60 * 24 * 7 // 7 days |
|
} |
|
} |
|
}, |
|
{ |
|
// Cache HTML pages with network-first for freshness |
|
urlPattern: /\.html$/i, |
|
handler: 'NetworkFirst', |
|
options: { |
|
cacheName: 'html-cache', |
|
expiration: { |
|
maxEntries: 20, |
|
maxAgeSeconds: 60 * 60 * 24 // 1 day |
|
}, |
|
networkTimeoutSeconds: 2 |
|
} |
|
} |
|
] |
|
}, |
|
manifest: { |
|
name: 'aitherboard - Decentralized Messageboard on Nostr', |
|
short_name: 'aitherboard', |
|
description: 'A decentralized messageboard built on the Nostr protocol. Create threads, comment, react, and zap in a censorship-resistant environment.', |
|
theme_color: '#f1f5f9', |
|
background_color: '#ffffff', |
|
display: 'standalone', |
|
icons: [ |
|
{ |
|
src: 'favicon.ico', |
|
sizes: '64x64', |
|
type: 'image/x-icon' |
|
}, |
|
{ |
|
src: 'apple-touch-icon-180x180.png', |
|
sizes: '180x180', |
|
type: 'image/png', |
|
purpose: 'any maskable' |
|
}, |
|
{ |
|
src: 'apple-touch-icon-152x152.png', |
|
sizes: '152x152', |
|
type: 'image/png' |
|
}, |
|
{ |
|
src: 'apple-touch-icon-144x144.png', |
|
sizes: '144x144', |
|
type: 'image/png' |
|
}, |
|
{ |
|
src: 'apple-touch-icon-120x120.png', |
|
sizes: '120x120', |
|
type: 'image/png' |
|
}, |
|
{ |
|
src: 'apple-touch-icon-114x114.png', |
|
sizes: '114x114', |
|
type: 'image/png' |
|
} |
|
] |
|
}, |
|
devOptions: { |
|
enabled: false, |
|
suppressWarnings: true // Suppress service worker warnings in dev mode |
|
} |
|
}), |
|
{ |
|
name: 'generate-healthz', |
|
buildStart() { |
|
try { |
|
execSync('node scripts/generate-healthz.js', { stdio: 'inherit' }); |
|
} catch (error) { |
|
console.warn('Failed to generate healthz.json:', error); |
|
} |
|
} |
|
} |
|
], |
|
server: { |
|
port: 5173, |
|
strictPort: false, |
|
fs: { |
|
// Allow serving files from the project root (including static directory if needed) |
|
allow: ['..'] |
|
} |
|
}, |
|
build: { |
|
target: 'esnext', |
|
sourcemap: false, |
|
manifest: false, |
|
minify: 'terser', |
|
terserOptions: { |
|
compress: { |
|
drop_console: ['log', 'debug'], // Remove console.log and console.debug in production, keep error/warn |
|
passes: 2, // Multiple passes for better compression |
|
} |
|
}, |
|
rollupOptions: { |
|
onwarn(warning, warn) { |
|
// Suppress warning about highlight.js default import - it's used in reactive contexts that Vite can't detect |
|
if (warning.message && |
|
typeof warning.message === 'string' && |
|
(warning.message.includes('highlight.js') || warning.message.includes('"default" is imported')) && |
|
(warning.message.includes('never used') || warning.message.includes('but never used'))) { |
|
return; |
|
} |
|
warn(warning); |
|
} |
|
} |
|
} |
|
});
|
|
|