u
This commit is contained in:
@@ -158,6 +158,55 @@ const sharedServer = {
|
||||
},
|
||||
};
|
||||
|
||||
function nginxHeadersPreviewPlugin() {
|
||||
return {
|
||||
name: 'nginx-headers-preview',
|
||||
configurePreviewServer(server) {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
const url = (req.url || '').split('?')[0];
|
||||
|
||||
// Never touch API requests (proxied to backend)
|
||||
if (url.startsWith('/api')) {
|
||||
return next();
|
||||
}
|
||||
|
||||
// --- Security Headers (from deploy/nginx-dashfront.conf lines 72-76) ---
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||||
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
|
||||
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||
res.setHeader('Permissions-Policy', 'camera=(self), microphone=(), geolocation=()');
|
||||
|
||||
// --- Caching Rules (from deploy/nginx-dashfront.conf lines 129-166) ---
|
||||
if (/^\/(sw\.js|registerSW\.js|workbox-[a-f0-9]+\.js)$/.test(url)) {
|
||||
// Zero caching for Service Worker & registration scripts
|
||||
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
res.setHeader('Pragma', 'no-cache');
|
||||
res.setHeader('Expires', '0');
|
||||
} else if (/^\/(manifest\.webmanifest|favicon\.svg|icons\/.*)$/.test(url)) {
|
||||
// 1 hour for web manifest & icons
|
||||
res.setHeader('Cache-Control', 'public, max-age=3600');
|
||||
res.setHeader('Vary', 'Accept-Encoding');
|
||||
} else if (url.startsWith('/assets/')) {
|
||||
// 1 year immutable for hashed assets
|
||||
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
res.setHeader('Vary', 'Accept-Encoding');
|
||||
} else if (url.endsWith('.wasm')) {
|
||||
// 1 year immutable for WASM binaries
|
||||
res.setHeader('Content-Type', 'application/wasm');
|
||||
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
} else if (url === '/' || url === '/index.html' || !path.extname(url)) {
|
||||
// HTML5 SPA Entry / Fallback: Zero caching
|
||||
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
res.setHeader('Pragma', 'no-cache');
|
||||
res.setHeader('Expires', '0');
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig(({ command }) => ({
|
||||
resolve: sharedResolve,
|
||||
build: {
|
||||
@@ -231,6 +280,7 @@ export default defineConfig(({ command }) => ({
|
||||
},
|
||||
plugins: [
|
||||
react(),
|
||||
nginxHeadersPreviewPlugin(),
|
||||
...(command === 'build'
|
||||
? [
|
||||
VitePWA({
|
||||
|
||||
Reference in New Issue
Block a user