denoland / fresh

The next-gen web framework.
https://fresh.deno.dev
MIT License
12.05k stars 605 forks source link

Fresh service worker #982

Open argyleink opened 1 year ago

argyleink commented 1 year ago

Service workers could save a ton of server load. Fortunately, Fresh has all the information needed to automatically generate a meaningful service worker: routes, assets, bundles…

I'm here to request that Fresh integrated service workers out of the box 😅

SW could cache…

Seems like there's an opportunity here to both makes Fresh projects faster and reduce server and cdn loads.

mfulton26 commented 1 year ago

I tried creating a Fresh plugin the other day to support serving a Fresh app offline via a service worker. I got blocked by service workers not supporting 2 things:

  1. top-level await
  2. dynamic import()

I think top-level await can be worked around by wrapping code inside of an asynchronous IIFE but I couldn't find a way around the dynamic import(). Shimport might work but I started digging into why a dynamic import() was needed and I realized it was from denoflate pulled in by esbuild. Running esbuild using WASM inside a service worker might have some use cases but I think caching the precompiled JavaScript files to hydrate islands would typically be better (fewer resources needed on the client in the service worker plus less CPU usage).

After realizing that I wanted to experiment with what a solution might look like so I rolled something more basic than Fresh but works offline: https://github.com/mfulton26/offline-mpa/. It is server-side rendered but instead of islands I'm doing full page hydration for simplicity but the idea should be the same. Almost all the code is reused between the server and the service worker. The main differences are that the server bundles JS on-demand while the service worker pre-downloads those bundles, caches them, and then serves those from the cache.

Can a similar pattern to what I was able to get working in my offline-mpa be used here in Fresh? I think the main blocker at the moment is that ServerContext in Fresh depends on the Bundler but if that can be injected when run on the server and be substituted with a cache loading/serving solution for a service worker then offline support (via a plugin?) can become a reality for Fresh!

mfulton26 commented 9 months ago

The new ahead-of-time builds should be usable as a manifest for a service worker. I feel like Fresh is already in a pretty close state to supporting offline apps. I think if any esbuild loading code were made conditional (e.g. via dynamic import) then bundling bundle most of the app as a service worker should work well as most code is "universal" (i.e. can be run in Deno and browser contexts).

Lack of official offline support is the main blocker for my team and me to using Fresh at work. @marvinhagemeister, do you think offline support as an official plugin aligns with Fresh's vision/scope/etc.? How might we get such prioritized? I can try doing a PR myself but I'm not confident in my familiarity with the codebase, etc.

marvinhagemeister commented 8 months ago

So far the interest in offline support is very low compared to all the other features. That's why it's not on the roadmap. I'm definitely open to accepting PRs if folks want to put in the work for that.