Allow better composability of fetch handlers
Nobody has claimed this yet.
- Dominant language
- Bikeshed
- Stars
- 3.6k
- Forks
- 324
- Avg merge
- 14d 22h
- Merged PRs (30d)
- 1
Description
I'm working on implementing default service worker support for Parcel. We'd like to inject some code into service workers at build time to handle Parcel generated assets, but still allow users to write custom code to handle other types of requests themselves (e.g. site content, APIs, etc.).
Currently, if a fetch handler does not call event.respondWith() synchronously within the handler, the event continues propagating to the next handler and so on. This is quite useful for allowing fallback, either to another handler or to the browser. However, if the logic to determine whether to respond to a request or not is asynchronous (e.g. loading something from cache or IDB), then it's impossible. By the time you've decided to respond, it's too late - the request has already been handled by something else.
I would like a way to make a decision about whether to respond to a fetch event asynchronously. I can think of two options, but I'm open to others:
event.continuePropagation()- the opposite ofstopPropagation(). You callevent.respondWith()as normal, but once you've decided not to actually respond, you continue propagation to the next handler.
self.addEventListener('fetch', event => {
event.respondWith(async () => {
if (await shouldRespond(event.request)) {
return getResponse(event.request);
}
event.continuePropagation();
}());
});
- Allow
event.respondWith()to be called from within anevent.waitUntil()promise. This one might not work because I believewaitUntilcauses the worker to wait, not the request, but I could be wrong.
self.addEventListener('fetch', event => {
event.waitUntil(async () => {
if (await shouldRespond(event.request)) {
return event.respondWith(getResponse(event.request));
}
}());
});
Previous discussions
This has previously been discussed in 2016 in #836, and probably a few other issues as well. The recommendation at the time seemed to be to use a middleware pattern. This works well if the service worker is all written together, but when tooling like Parcel wants to inject logic into a service worker it falls down. We would like to avoid inventing our own service worker middleware framework or requiring users use a specific library to write their service worker.
See also this twitter thread: https://twitter.com/devongovett/status/1185961634029654016, and our RFC for service worker generation in Parcel: https://github.com/parcel-bundler/parcel/issues/3661.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the previous discussion in issue #836 and the linked Parcel service-worker generation RFC. Define and document an agreed way for asynchronously deciding whether a fetch event should respond or continue, with behavior that supports injected handlers alongside user handlers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100