Files
catarrh 8c442bf7b6 fix(offline): surface degraded/missing preloads, join re-entrant runs, cache manifest to IDB
- loadManifest() goes through DataCache.fetchWithFallback: the file list is
  written to IDB and survives SW-cache eviction; a run with the reduced
  fallback set is flagged and shown as degraded (new i18n en/ru/cu).
- 404 answers are counted as 'missing' (deployment drift) with a
  preload-missing diag entry, instead of silently reporting Done.
- preload() is re-entrancy safe: concurrent calls join the in-flight run.
- versions.json is loaded once per session (was fetched per translation).
- Write-through failures in fetchWithFallback()/fetch() log idb-write-fail.
- preload-manifest.json SW route is NetworkFirst (fresh coverage online).
- Manifest now also covers the shared/lives + shared/commands fallbacks.
2026-10-04 17:14:33 +03:00

82 lines
2.5 KiB
TypeScript

import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
import { resolve } from 'path';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
tailwindcss(),
VitePWA({ registerType: 'prompt',
workbox: {
skipWaiting: false,
clientsClaim: false,
globPatterns: ['**/*.{js,css,html,woff,png}'],
globIgnores: ['**/data/**'],
maximumFileSizeToCacheInBytes: 20 * 1024 * 1024,
runtimeCaching: [
{
// The preload file list must be fresh when online; a stale copy
// silently loses coverage. Offline falls back to the SW copy.
urlPattern: /\/data\/shared\/preload-manifest\.json$/,
handler: 'NetworkFirst',
options: {
cacheName: 'ponomar-manifest',
networkTimeoutSeconds: 3,
},
},
{
urlPattern: /\/data\/.*\.json$/,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'ponomar-data',
expiration: { maxEntries: 200, maxAgeSeconds: 60 * 60 * 24 * 30 },
},
},
{
urlPattern: /\/data\/.*\.text$/,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'ponomar-bible',
expiration: { maxEntries: 100, maxAgeSeconds: 60 * 60 * 24 * 30 },
},
},
{
urlPattern: /\/fonts\/.*\.woff2?$/,
handler: 'CacheFirst',
options: {
cacheName: 'ponomar-fonts',
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
},
},
],
},
manifest: {
id: '/',
name: 'Ponomar — Orthodox Calendar',
short_name: 'Ponomar',
description: 'Orthodox Church calendar and liturgical information',
start_url: '/',
display: 'standalone',
background_color: '#f5f0e8',
theme_color: '#1a1a2e',
orientation: 'portrait',
icons: [
{ src: '/icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any maskable' },
{ src: '/icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable' },
],
},
}),
],
server: {
port: 5173,
strictPort: false,
},
build: {
outDir: 'dist',
sourcemap: true,
},
define: {
__BUILD_DATE__: JSON.stringify(new Date().toISOString().slice(0, 10)),
},
publicDir: 'static',
});