feat: PWA manifest + build-time service worker (#15)
Applies Replit PR #28 feature on top of current main: - Root sw.js template with __PRECACHE_URLS__ placeholder - generate-sw Vite plugin: reads build manifest, injects actual asset URLs - manifest: true in Vite build config for asset manifest generation - SW registration gated to import.meta.env.PROD (no dev interference) - Preserves existing manifest.json and public/sw.js as dev fallback
This commit is contained in:
@@ -188,11 +188,6 @@
|
||||
<button id="chat-send">></button>
|
||||
</div>
|
||||
<script type="module" src="./js/main.js"></script>
|
||||
<script>
|
||||
// Register service worker for PWA / offline support
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
||||
}
|
||||
</script>
|
||||
<!-- SW registration is handled by main.js in production builds only -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -135,3 +135,8 @@ function main() {
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
// Register service worker only in production builds
|
||||
if (import.meta.env.PROD && 'serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
||||
}
|
||||
|
||||
39
sw.js
Normal file
39
sw.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/* sw.js — Matrix PWA service worker
|
||||
* PRECACHE_URLS is replaced at build time by the generate-sw Vite plugin.
|
||||
* Registration is gated to import.meta.env.PROD in main.js, so this template
|
||||
* file is never evaluated by browsers during development.
|
||||
*/
|
||||
const CACHE_NAME = 'timmy-matrix-v1';
|
||||
const PRECACHE_URLS = __PRECACHE_URLS__;
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME).then(cache => cache.addAll(PRECACHE_URLS))
|
||||
);
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(keys =>
|
||||
Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k)))
|
||||
)
|
||||
);
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
if (event.request.method !== 'GET') return;
|
||||
event.respondWith(
|
||||
caches.match(event.request).then(cached => {
|
||||
if (cached) return cached;
|
||||
return fetch(event.request).then(response => {
|
||||
if (!response || response.status !== 200 || response.type !== 'basic') {
|
||||
return response;
|
||||
}
|
||||
caches.open(CACHE_NAME).then(cache => cache.put(event.request, response.clone()));
|
||||
return response;
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -1,4 +1,35 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
|
||||
/** Vite plugin: generates dist/sw.js with precache URLs from the build manifest. */
|
||||
function generateSW() {
|
||||
return {
|
||||
name: 'generate-sw',
|
||||
apply: 'build',
|
||||
closeBundle() {
|
||||
const staticAssets = [
|
||||
'/',
|
||||
'/manifest.json',
|
||||
'/icons/icon-192.svg',
|
||||
'/icons/icon-512.svg',
|
||||
];
|
||||
|
||||
try {
|
||||
const manifest = JSON.parse(readFileSync('dist/.vite/manifest.json', 'utf-8'));
|
||||
for (const entry of Object.values(manifest)) {
|
||||
staticAssets.push('/' + entry.file);
|
||||
if (entry.css) entry.css.forEach(f => staticAssets.push('/' + f));
|
||||
}
|
||||
} catch { /* manifest may not exist in dev */ }
|
||||
|
||||
const template = readFileSync('sw.js', 'utf-8');
|
||||
const out = template.replace('__PRECACHE_URLS__', JSON.stringify(staticAssets, null, 4));
|
||||
writeFileSync('dist/sw.js', out);
|
||||
|
||||
console.log('[generate-sw] wrote dist/sw.js with', staticAssets.length, 'precache URLs');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
root: '.',
|
||||
@@ -6,6 +37,7 @@ export default defineConfig({
|
||||
outDir: 'dist',
|
||||
assetsDir: 'assets',
|
||||
target: 'esnext',
|
||||
manifest: true,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
@@ -14,6 +46,7 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [generateSW()],
|
||||
server: {
|
||||
host: true,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user