Hi, wondering if it's possible to simply cache everything rather than just what the user sees. It seems if they install with this sw and then open the app the first time offline, they don't have anything cached. Also, if they navigate to another page or load a font, it fails if offline. My whole app is < 1mb and I'd love to just cache it all on install. Thanks in advance.
I've modified Navin's service worker to do just that:
import{build,files,version}from"$service-worker";constworker=selfasunknownasServiceWorkerGlobalScope;constSTATIC_CACHE_NAME=`cache${version}`;constAPP_CACHE_NAME=`offline${version}`;// hard-coded list of app routes we want to preemptively cacheconstroutes=["/"];// hard-coded list of other assets necessary for page load outside our domainconstcustomAssets=["https://fonts.googleapis.com/css2?family=Inter:wght@400;700;800&display=swap","https://unpkg.com/ress/dist/ress.min.css","https://fonts.gstatic.com/s/inter/v11/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2",];// `build` is an array of all the files generated by the bundler,// `files` is an array of everything in the `static` directory// `version` is the current version of the appconstaddDomain=(assets:string[])=>assets.map((f)=>self.location.origin+f);// we filter the files because we don't want to cache logos for iOS// (they're big and largely unused)// also, we add the domain to our assets, so we can differentiate routes of our// app from those of other apps that we cacheconstourAssets=addDomain([...files.filter((f)=>!/\/icons\/(apple.*?|original.png)/.test(f)),...build,...routes,]);consttoCache=[...ourAssets,...customAssets];conststaticAssets=newSet(toCache);worker.addEventListener("install",(event)=>{event.waitUntil(caches.open(STATIC_CACHE_NAME).then((cache)=>{returncache.addAll(toCache);}).then(()=>{worker.skipWaiting();}));});worker.addEventListener("activate",(event)=>{event.waitUntil(caches.keys().then(async (keys)=>{// delete old cachesfor (constkeyofkeys){if (key!==STATIC_CACHE_NAME&&key!==APP_CACHE_NAME){awaitcaches.delete(key);}}worker.clients.claim();}));});/**
* Fetch the asset from the network and store it in the cache.
* Fall back to the cache if the user is offline.
*/asyncfunctionfetchAndCache(request:Request){constcache=awaitcaches.open(APP_CACHE_NAME);try{constresponse=awaitfetch(request);cache.put(request,response.clone());returnresponse;}catch (err){constresponse=awaitcache.match(request);if (response){returnresponse;}throwerr;}}worker.addEventListener("fetch",(event)=>{if (event.request.method!=="GET"||event.request.headers.has("range")){return;}consturl=newURL(event.request.url);// don't try to handle e.g. data: URIsconstisHttp=url.protocol.startsWith("http");constisDevServerRequest=url.hostname===self.location.hostname&&url.port!==self.location.port;constisStaticAsset=staticAssets.has(url.href);constskipBecauseUncached=event.request.cache==="only-if-cached"&&!isStaticAsset;if (isHttp&&!isDevServerRequest&&!skipBecauseUncached){event.respondWith((async ()=>{// always serve static files and bundler-generated assets from cache.// if your application has other URLs with data that will never change,// set this variable to true for them, and they will only be fetched once.constcachedAsset=isStaticAsset&&(awaitcaches.match(event.request));returncachedAsset||fetchAndCache(event.request);})());}});
Simply set the routes array to a list of all routes you want to cache and add URLs to fonts, external CSS, etc. that you want to cache to the customAssets array.
Note that I use a cache-only strategy, so upon updating your app, you'll have to refresh the app twice to see the new content. You can fix this by either employing an instant force refresh (see codyanhorn.tech/blog/pwa-reload-pa...) or notify the user that an update is available (see medium.com/progressive-web-apps/pw...)
hey good article. i used this setup for a sveltekit app and it works great but i was having issue with subsequent updates. it would never pick up the new deploy because the index.html was cached i believe? i am also using the static prerender sveltekit adapter so possibly that is related. i ended up having to modify app.html for it to detect a change and then it would pick up the new service worker. have you run into this issue?
I use the vercel adapter when deploying. I haven't used ssg with sveltekit yet. But I do have an issue whenever I upgrade the packages. Sveltekit throws module not defined errors if i don't set the version to "next" instead of something like "^1.0.0". Have you joined their discord server?
If you still need an answer, change timestamp to version. I followed the Svelte docs for service workers. Be sure to change timestamp anywhere it appears in your code as well.
Navin, used your code but the serviceworker is not being registered. It's giving me a 404 error. I added the serviceworker to src folder, manifest in static as in your code.
Is your code still working after their latest update? In the sveltekit doc, they mentioned that vite register the serviceworker. Is there any configuration for vite registering the service worker?
My main job is not in IT, but I do have a CS degree and have been programming for over 20 years (only born in 1984). I hate dealing with Servers, and want Graph Databases to be the new norm.
Hi, wondering if it's possible to simply cache everything rather than just what the user sees. It seems if they install with this sw and then open the app the first time offline, they don't have anything cached. Also, if they navigate to another page or load a font, it fails if offline. My whole app is < 1mb and I'd love to just cache it all on install. Thanks in advance.
Love this article by the way
I've modified Navin's service worker to do just that:
Simply set the
routesarray to a list of all routes you want to cache and add URLs to fonts, external CSS, etc. that you want to cache to thecustomAssetsarray.Note that I use a cache-only strategy, so upon updating your app, you'll have to refresh the app twice to see the new content. You can fix this by either employing an instant force refresh (see codyanhorn.tech/blog/pwa-reload-pa...) or notify the user that an update is available (see medium.com/progressive-web-apps/pw...)
Awesome! Thanks : )
No prob! :)
Hi, are we allowed to use the service worker snippet? Under which license does your project stand?
You can use it to your liking
hey good article. i used this setup for a sveltekit app and it works great but i was having issue with subsequent updates. it would never pick up the new deploy because the index.html was cached i believe? i am also using the static prerender sveltekit adapter so possibly that is related. i ended up having to modify app.html for it to detect a change and then it would pick up the new service worker. have you run into this issue?
I use the vercel adapter when deploying. I haven't used ssg with sveltekit yet. But I do have an issue whenever I upgrade the packages. Sveltekit throws module not defined errors if i don't set the version to "next" instead of something like "^1.0.0". Have you joined their discord server?
I was having the same issue, but I modified his script slightly and it worked again. See my comment above :)
I tried to follow your tutorial but I got an error:
RollupError: "timestamp" is not exported by ".svelte-kit/generated/service-worker.js", imported by "src/service-worker.ts".Do you know anything about this? I'm at a loss as how to fix this.
If you still need an answer, change
timestamptoversion. I followed the Svelte docs for service workers. Be sure to changetimestampanywhere it appears in your code as well.Navin, used your code but the serviceworker is not being registered. It's giving me a 404 error. I added the serviceworker to src folder, manifest in static as in your code.
Is your code still working after their latest update? In the sveltekit doc, they mentioned that vite register the serviceworker. Is there any configuration for vite registering the service worker?
also a great tool to make manifest.json
app-manifest.firebaseapp.com/
Is there a way to route the user to the page they were most recently on when they reopen the app?
I would think sveltekit would do all this automatically.
I like your firebase articles