fix(ui-server-auth): bust poisoned asset caches (#2196)
This commit is contained in:
@@ -23,7 +23,7 @@ pnpm -F @proj-airi/ui-server-auth build
|
||||
|
||||
## Deployment
|
||||
|
||||
`pnpm -F @proj-airi/ui-server-auth build` writes to `apps/ui-server-auth/dist`. Vue Router owns `/ui/*`, while Vite assets are served from root `/assets/*` so Cloudflare Pages can serve static files without rewriting nested asset paths. `public/_redirects` scopes the SPA rewrite to `/ui/*`, and the top-level `public/404.html` keeps missing assets and other unknown paths as HTTP 404 responses.
|
||||
`pnpm -F @proj-airi/ui-server-auth build` writes to `apps/ui-server-auth/dist`. Vue Router owns `/ui/*`, while Vite assets are served from root `/assets-v2/*` so Cloudflare Pages can serve static files without rewriting nested asset paths. The versioned namespace moves existing clients away from previously poisoned `/assets/*` browser cache entries. Both namespaces use `Cache-Control: public, no-cache`, allowing browsers to retain files only when Pages revalidates them. `public/_redirects` scopes the SPA rewrite to `/ui/*`, and the top-level `public/404.html` keeps missing assets and other unknown paths as HTTP 404 responses.
|
||||
|
||||
The production GitHub Actions workflow deploys this app to the Cloudflare Pages project `moeru-ai-airi-auth` with separate auth-account credentials:
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/assets/*
|
||||
cache-control: max-age=31536000
|
||||
cache-control: immutable
|
||||
cache-control: public, no-cache
|
||||
|
||||
/assets-v2/*
|
||||
cache-control: public, no-cache
|
||||
|
||||
@@ -23,4 +23,12 @@ describe('cloudflare Pages routing', () => {
|
||||
expect(notFoundPage).toContain('<title>Page not found</title>')
|
||||
expect(redirects).toContain('/ui/* / 200')
|
||||
})
|
||||
|
||||
it('requires old and current asset namespaces to revalidate cached responses', async () => {
|
||||
const headers = await readFile(resolve(publicDirectory, '_headers'), 'utf8')
|
||||
|
||||
expect(headers).toContain('/assets/*\n cache-control: public, no-cache')
|
||||
expect(headers).toContain('/assets-v2/*\n cache-control: public, no-cache')
|
||||
expect(headers).not.toContain('immutable')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,6 +12,16 @@ import VueRouter from 'vue-router/vite'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
// NOTICE:
|
||||
// Keep this namespace distinct from `/assets/`, where an earlier Pages SPA
|
||||
// fallback allowed missing JavaScript URLs to cache index.html as immutable.
|
||||
// Root cause: the old asset cache policy outlived the deployment that restored
|
||||
// those files, so affected browsers cannot observe corrected response headers.
|
||||
// Source/context: `apps/ui-server-auth/public/_headers` and `public/404.html`.
|
||||
// Removal condition: keep the namespace permanently; reusing `/assets/` can
|
||||
// reactivate poisoned browser entries that remain fresh for up to one year.
|
||||
const assetsDirectory = 'assets-v2'
|
||||
|
||||
export default defineConfig({
|
||||
base: '/',
|
||||
optimizeDeps: {
|
||||
@@ -44,6 +54,7 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
build: {
|
||||
assetsDir: assetsDirectory,
|
||||
emptyOutDir: true,
|
||||
manifest: true,
|
||||
outDir: resolve(join(import.meta.dirname, 'dist')),
|
||||
@@ -58,8 +69,8 @@ export default defineConfig({
|
||||
// Keep analytics as the source-domain name, but explicitly map its
|
||||
// public URL to a neutral chunk name that filter lists cannot infer.
|
||||
return containsAnalyticsModule
|
||||
? 'assets/chunk-[hash].js'
|
||||
: 'assets/[name]-[hash].js'
|
||||
? `${assetsDirectory}/chunk-[hash].js`
|
||||
: `${assetsDirectory}/[name]-[hash].js`
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user