Files
joshuaandClaude Opus 5.5 7b3d121151 V1.12.3: live updates behind any proxy, fewer requests
- Live updates start on plain requests and move up to a websocket when
  one gets through. The site used to ask for the websocket first, with
  no way back: behind a proxy that does not pass the upgrade, nothing
  live arrived at all.
- A browser asks the API's leave before a request, the site and the API
  being on different hosts. It now remembers the answer for two hours,
  where it used to ask before nearly every request.
- A built file is kept by the browser for good: its name changes when
  its contents do. Each used to be checked again on every page load.
- For a real websocket through nginx, the blocks that pass requests to
  the API need "proxy_http_version 1.1", "proxy_set_header Upgrade
  $http_upgrade" and "proxy_set_header Connection "upgrade"".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:04:45 +02:00

38 lines
1.3 KiB
TypeScript

import { existsSync } from 'node:fs'
import { join } from 'node:path'
import react from '@vitejs/plugin-react'
import compression from 'compression'
import { defineConfig, type Connect, type Plugin } from 'vite'
// `vite preview` is what serves the built site, so the two things a web
// server would be set up to do are done here.
const servePreview: Plugin = {
name: 'serve-preview',
configurePreviewServer(server) {
const assets = join(server.config.root, server.config.build.outDir)
// Typed for Express, and at home in any Node server.
server.middlewares.use(compression() as Connect.NextHandleFunction)
// A built file carries a hash of its contents in its name, so a browser
// can keep it for good and never ask again. Only for files that are
// there: a name from an older build must not be remembered as missing.
server.middlewares.use((req, res, next) => {
const path = (req.url ?? '').split('?')[0]
if (path.startsWith('/assets/') && !path.includes('..') && existsSync(join(assets, path))) {
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
}
next()
})
},
}
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), servePreview],
preview: {
host: true,
port: 5173,
allowedHosts: ['the-sunken-reach.crosscode.co.za'],
},
})