[w3c/ServiceWorker] Allow overlapping scopes (#1085)

>From my understanding, #566 relates to allowing multiple/dynamic scopes for a single SW, and #921 relates to allowing multiple SW at the same scope. However I think SW should allow overlapping scopes as a separate case.

What I mean by overlapping scopes is one site could register two SWs at different but nested scopes like this:

`https://example.com/root-sw.js`
`https://example.com/path/path-sw.js`

Note `path-sw.js` is within the scope of `root-sw.js`. I can't find much information on what is actually specified as happening in this situation, but I did see one comment saying "it's implementation defined, don't do it". I also tried it on Chrome and totally couldn't figure out what it was actually doing, but it looked like it picked one SW and just permanently used that. However I think there are valid use-cases around this.

In the above example I would like `root-sw.js` gets all fetch events on the origin, except for anything under `/path/`, which then goes to `path-sw.js`. For example some mappings would be:

`https://example.com/index.html` -> `root-sw.js`
`https://example.com/otherpath/index.html` -> `root-sw.js`
`https://example.com/path/index.html` -> `path-sw.js`
`https://example.com/path/anotherpath/index.html` -> `path-sw.js`

## Use cases
One potential disadvantage of web apps over traditional installed desktop apps is if an update breaks or changes something, users cannot easily roll back to an older version. This can be mitigated by making old versions of a web app available as well.

To me, the obvious way to do that would be something like this:

`https://myapp.com/` is the latest version and auto-updates
`https://myapp.com/v1/` would be specifically version 1
`https://myapp.com/v2/` would be specifically version 2, etc.

Then users just use `myapp.com` and if anything goes wrong they can roll back to `myapp.com/v1`, for example.

However adding SW-based offline support in this scenario requires that there be SWs at the following scopes:

`https://myapp.com/`
`https://myapp.com/v1/`
`https://myapp.com/v2/`

But note all the versioned URLs fall under the scope of the origin-level SW. Since as far as I can tell SW does not support this case, it forces the URL scheme to be changed. The next best workaround seems to be to use another path for the latest version, e.g.

`https://myapp.com/latest/`

and now none of the SW scopes overlap. However it seems awkward that we have to change the URL structure of our app solely because of this aspect of SW. Also it's not such a nice URL - it is easier for customers to remember simply `myapp.com`, whereas this way they may have to remember "myapp.com slash something". (Obviously myapp.com can redirect to myapp.com/latest, but the user doesn't necessarily know that will work, and will permanently see myapp.com/latest in their URL bar.)

Another use case might be using paths for other services, e.g.:

`myapp.com/` serves a web page entry point with a SW that handles notifications and such
`myapp.com/static/` serves static content with a long-term caching SW
`myapp.com/api/` serves API content with a short-term caching SW

In this case again the URL structure has to be changed. Alternatively in both cases you could write one master SW that handles all versions or all cases, but that significantly increases the complexity of the SW script. It's nice to have little modular SWs that handle specific paths in specialised ways.

## Spec changes
This seems relatively straightforward to specify: fetch events go to the SW with the "nearest" scope. I'd probably better define that as the SW with the longest scope that the fetch event still falls under.

This doesn't need any new API surface and still enables these use cases. It just better defines what currently appears to be murky/undocumented/undefined behavior.

I suspect there may need to be special provisions for updating SWs themselves. For example in the original example, it is unlikely the web developer wants the fetch for `path-sw.js` when registering that service worker to be handled by a previously registered `root-sw.js` (this seems likely to just cause headaches with stale cached versions). I can't think of any use case for wanting one SW to handle the fetch event for another SW, so it seems reasonable to just say they are an exception.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/ServiceWorker/issues/1085

Received on Friday, 3 March 2017 14:29:06 UTC