diff --git a/services/frontend/nginx.conf b/services/frontend/nginx.conf index 9186aa774..2b127fea3 100644 --- a/services/frontend/nginx.conf +++ b/services/frontend/nginx.conf @@ -4,16 +4,33 @@ server { root /usr/share/nginx/html; index index.html; - location /assets/ { - try_files $uri =404; - access_log off; - add_header Cache-Control "public, max-age=31536000, immutable"; - } + gzip on; + gzip_static on; + gzip_vary on; + gzip_min_length 256; + gzip_comp_level 6; + gzip_proxied any; + gzip_types + text/plain + text/css + text/javascript + application/javascript + application/json + application/xml + application/wasm + image/svg+xml + font/ttf + font/otf + font/woff + font/woff2; - location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|webp|txt|json|map)$ { + # Vite-built, content-hashed bundle output. Filename changes when bytes change, + # so we can hand out a one-year immutable cache. ^~ ensures this prefix wins + # over any regex location. + location ^~ /assets/ { try_files $uri =404; access_log off; - add_header Cache-Control "public, max-age=31536000, immutable"; + add_header Cache-Control "public, max-age=31536000, immutable" always; } location = /healthz { @@ -21,7 +38,11 @@ server { add_header Content-Type text/plain; } + # SPA entry document and unhashed root statics (favicon.png, banner.webp, ...). + # These have stable URLs but mutable content, so we force revalidation on every + # request. ETag/Last-Modified make 304s cheap. location / { + add_header Cache-Control "no-cache" always; try_files $uri /index.html; } -} \ No newline at end of file +} diff --git a/services/frontend/vite.config.mjs b/services/frontend/vite.config.mjs index a6ecaa66b..809e8f5f6 100644 --- a/services/frontend/vite.config.mjs +++ b/services/frontend/vite.config.mjs @@ -8,7 +8,14 @@ import istanbul from 'vite-plugin-istanbul' export default defineConfig({ build: { - target: "esnext" + target: "esnext", + rollupOptions: { + output: { + entryFileNames: 'assets/[hash].js', + chunkFileNames: 'assets/[hash].js', + assetFileNames: 'assets/[hash][extname]', + }, + }, }, css: { preprocessorOptions: {