Skip to content

Add local SSR/CSR to Service Workers. #3498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Mooshua opened this issue Jan 21, 2022 · 1 comment · May be fixed by #13791
Open

Add local SSR/CSR to Service Workers. #3498

Mooshua opened this issue Jan 21, 2022 · 1 comment · May be fixed by #13791
Labels
feature / enhancement New feature or request service worker Stuff related to service workers
Milestone

Comments

@Mooshua
Copy link

Mooshua commented Jan 21, 2022

Describe the problem

Currently, it is difficult to do “offline first” in SvelteKit. If you want to bring a page from the cache instead of going over the web (especially in cases where the web is unavailable), you can only provide responses for when the server was pinged, with the server’s SSR instead of your own. With Kit’s client-side routing, it is unknown if a site will even be loaded at all.

Using Workbox would help, but that still doesn’t solve the problem of serving dynamic svelte content to users from a service worker.

Describe the proposed solution

The proposed solution would be to export new functionality to the service workers, such as “render_page”, which will look up the corresponding URL in an internal dictionary and perform SSR rendering with required props.

Another solution to this issue would be to expose more metadata, and a CSR html template, to the service worker. It’d have the same effect while being smaller and more flexible, and probably much easier to implement. This would be a great solution as well, as it’s probably faster do to CSR once than to do SSR and then hydrate it.

This would enable offline-first usage at high scale. A good example would be a storefront—it’s much more efficient to cache some JSON data of all products than to store all of the HTML for a single product.

Alternatives considered

Initially, I considered doing some voodoo magic to create an HTML template which would work to perform CSR upon loading in an offline situation, but this proved to be extraordinarily difficult, as it is hard to tell which Vite bundles are needed per-page with the information provided (not that you can’t find a way to do it…)

I’ve also tried caching the SSR pages, but again, it is a lot of content, and wouldn’t be readable eg. For a storefront or blog.

Importance

nice to have

Additional Information

No response

@Mooshua Mooshua changed the title Local SSR/CSR on Service Workers. Add local SSR/CSR to Service Workers. Jan 22, 2022
@Rich-Harris Rich-Harris added the feature / enhancement New feature or request label Mar 6, 2022
@Rich-Harris Rich-Harris added this to the post-1.0 milestone Mar 6, 2022
@benmccann benmccann added the service worker Stuff related to service workers label Sep 6, 2022
@thomasfosterau
Copy link

I know it’s been almost three years... but I’m going to resurrect this because I’ve got a project where this would be a very valuable feature and it might be worth my while to draw the rest of the proverbial owl.

Essentially, I’m working on a SvelteKit app which has a lot of dynamic routes, most of which have data which can be stored/cached in IndexedDB (or an alternative storage solution). Currently, I can access IndexedDB in +page.ts, but that’s only available if the user has already visited the page. As a fallback, the service worker can serve a cached page, but that’s only possible if the user has previously visited the page. There would be some enormous user experience wins if the service worker could sensibly respond to any request.

The sort of API for this that would address the use cases I have would be:

  • The $service-worker module should export a respond function, which takes a FetchEvent and returns a Promise<Response>. The respond function would mostly work like the Server#respond method made available to adapters.
  • Any module available on the client would be made available in a service worker, such as $app/environment. This could be a separate issue, I don’t see what the problem would be with this besides needing sensible defaults.
  • $app/environment could provide a serviceWorker export, analogous to browser.
  • In a service worker, +layout.ts and +page.ts would run, but +layout.server.ts and +page.server.ts would not be run. Instead, there would be a +layout.worker.ts and +page.worker.ts files instead. +{layout,page}.worker.ts would be given a server() function, similar to how parent() works, and would get the properties available on FetchEvent instead of platform.
  • In a service worker, a +worker.ts file would substitute for +server.ts. Again, +worker.ts would be able to call sever() to run the +server.ts endpoint.

The SvelteKit codebase seems to have changed a bit since I last attempted a PR which added this functionality so I wouldn’t mind some guidance as to what a ‘mergeable' implementation would look like. In particular, I think there’s a trade-off to be made between flexibility and maintainability when it comes to how much code can realistically be shared between the server and service worker implementations — would an internal sui generis adapter for service workers be an option?

@thomasfosterau thomasfosterau linked a pull request May 15, 2025 that will close this issue
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature / enhancement New feature or request service worker Stuff related to service workers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants