Files
tefter/frontend/vite.config.ts
Senad Uka a9ea8c7f73 New notebook logo: spiral-bound page icon for favicon/PWA/desktop
SVG source in frontend/public/icon.svg, rendered to 192/512/maskable PNGs
and desktop/build/appicon.png; SVG favicon with PNG fallback; icons added
to the service-worker precache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 07:24:39 +02:00

68 lines
2.1 KiB
TypeScript

import { defineConfig, type Plugin } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { createHash } from 'node:crypto';
const version = process.env.TEFTER_VERSION || 'dev';
// Emits sw.js at build time with the precache list of all emitted assets,
// versioned by a hash of the file names (which themselves carry content hashes).
function serviceWorker(): Plugin {
return {
name: 'tefter-sw',
apply: 'build',
generateBundle(_opts, bundle) {
const assets = Object.keys(bundle)
.filter((f) => !f.endsWith('.map'))
.map((f) => '/' + f);
assets.push('/', '/manifest.webmanifest', '/icon.svg', '/icon-192.png', '/icon-512.png', '/icon-512-maskable.png');
const hash = createHash('sha256').update(assets.join(',') + version).digest('hex').slice(0, 12);
const sw = `// generated by vite.config.ts — do not edit
const CACHE = 'tefter-${'${'}HASH}';
const ASSETS = ${'${'}ASSETS};
self.addEventListener('install', (e) => {
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(ASSETS)).then(() => self.skipWaiting()));
});
self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys()
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
.then(() => self.clients.claim())
);
});
self.addEventListener('fetch', (e) => {
const url = new URL(e.request.url);
if (e.request.method !== 'GET' || url.origin !== location.origin) return;
if (url.pathname.startsWith('/api/')) return; // network-only; sync engine handles offline
e.respondWith(
caches.match(url.pathname === '/' || url.pathname === '/index.html' ? '/' : e.request).then(
(hit) => hit || fetch(e.request)
)
);
});
`
.replace('${HASH}', hash)
.replace('${ASSETS}', JSON.stringify(assets));
this.emitFile({ type: 'asset', fileName: 'sw.js', source: sw });
},
};
}
export default defineConfig({
plugins: [svelte(), serviceWorker()],
define: {
__TEFTER_VERSION__: JSON.stringify(version),
},
build: {
target: 'es2020',
sourcemap: false,
},
server: {
proxy: {
'/api': 'http://127.0.0.1:8420',
},
},
});