Skip to content
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

Updating "Using Service Worker" page #22682

Merged
merged 22 commits into from
Dec 17, 2022
Merged

Conversation

SphinxKnight
Copy link
Member

@SphinxKnight SphinxKnight commented Dec 2, 2022

Description

Update this page to remove "dated" information.

Motivation

I was translating the page for mdn/translated-content#10371 and was a bit saddened by the original page. So I went with contributing on the English one as well

Related issues and pull requests

mdn/yari#7645
#9679

@github-actions github-actions bot added the Content:WebAPI Web API docs label Dec 2, 2022
@SphinxKnight
Copy link
Member Author

I've done a first pass at it and plan to rework the diagrams before marking this as ready for review. That being written please let me know if you see something in the meantime.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 2, 2022

Preview URLs

Flaws (1)

URL: /en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
Title: Using Service Workers
Flaw count: 1

  • broken_links:
    • Can't resolve /en-US/docs/Web/HTTP/Header/Service-Worker-Allowed
External URLs (6)

URL: /en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
Title: Using Service Workers

(comment last updated: 2022-12-17 20:30:21)

@SphinxKnight
Copy link
Member Author

Summary of changes:

  • Diagrams
    • Changed diagrams to SVG for localization.
    • Removed diagrams with 95% of text, because accessibility primes
    • Moved skipWaiting() and clients.claim() mention to the text (where they were not explained)
  • Content
    • Removed/Minimized AppCache and "temporal" point of view since support has been good for a while now
    • Removed xref macros
    • Removed tags
    • Wording: removed "magic", "trivial", "trick"
    • Minimized "DevTools" content dependency

@SphinxKnight SphinxKnight marked this pull request as ready for review December 6, 2022 12:56
@SphinxKnight SphinxKnight requested a review from a team as a code owner December 6, 2022 12:56
@SphinxKnight SphinxKnight requested review from wbamberg and removed request for a team December 6, 2022 12:56
Copy link
Contributor

@OnkarRuikar OnkarRuikar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few nitpicks.
There is one more place, where Github isn't letting me make suggestions, where install verb is used as a noun: "the install and activation process for a new service worker".

@wbamberg
Copy link
Collaborator

@SphinxKnight this is awesome. I will take a look :).

Copy link
Collaborator

@wbamberg wbamberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great update, @SphinxKnight !


The previous attempt, _AppCache_, seemed to be a good idea because it allowed you to specify assets to cache really easily. However, it made many assumptions about what you were trying to do and then broke horribly when your app didn't follow those assumptions exactly. Read Jake Archibald's (unfortunately-titled but well-written) [Application Cache is a Douchebag](https://alistapart.com/article/application-cache-is-a-douchebag/) for more details.
Service workers fix these issues. Using a service worker you can easily set an app up to use cached assets first, thus providing a default experience even when offline, before then getting more data from the network (commonly known as "offline first"). This is already available with native apps, which is one of the main reasons native apps are often chosen over web apps.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Service workers fix these issues. Using a service worker you can easily set an app up to use cached assets first, thus providing a default experience even when offline, before then getting more data from the network (commonly known as "offline first"). This is already available with native apps, which is one of the main reasons native apps are often chosen over web apps.
Service workers fix these issues. Using a service worker you can set an app up to use cached assets first, thus providing a default experience even when offline, before then getting more data from the network (commonly known as "offline first"). This is already available with native apps, which is one of the main reasons native apps are often chosen over web apps.


> **Note:** From Firefox 84, AppCache has been removed ({{bug("1619673")}}). It has also been [removed](https://bugs.chromium.org/p/chromium/issues/detail?id=582750) from Chromium 95, and is deprecated in Safari.
A service worker functions like a proxy server, allowing you to modify requests and responses, replace them with items from its own cache.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A service worker functions like a proxy server, allowing you to modify requests and responses, replace them with items from its own cache.
A service worker functions like a proxy server, allowing you to modify requests and responses, or replace them with items from its own cache.

? Or alternatively "allowing you to modify requests and responses replacing them with items from its own cache." - if "modify" wants to be the same operation as "replace from cache" rather than an alternative.


Service workers should finally fix these issues. Service worker syntax is more complex than that of AppCache, but the trade-off is that you can use JavaScript to control your AppCache-implied behaviors with a fine degree of granularity, allowing you to handle this problem and many more. Using a Service worker you can easily set an app up to use cached assets first, thus providing a default experience even when offline, before then getting more data from the network (commonly known as [Offline First](https://offlinefirst.org/)). This is already available with native apps, which is one of the main reasons native apps are often chosen over web apps.
> **Note:** Before service workers, a previous attempt at fixing those issues was AppCache. This API has been deprecated and removed from browsers, and should not be used anymore.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could just omit this note. Surely at this point only historians know about AppCache?


## Setting up to play with service workers

These days, service workers are enabled by default in all modern browsers. To run code using service workers, you'll need to serve your code via HTTPS — Service workers are restricted to running across HTTPS for security reasons. GitHub is therefore a good place to host experiments, as it supports HTTPS. In order to facilitate local development, `localhost` is considered a secure origin by browsers as well.
Service workers are enabled by default in all modern browsers. To run code using service workers, you'll need to serve your code via HTTPS — Service workers are restricted to running across HTTPS for security reasons. A server supporting HTTPS is necessary. To host experiments, you can use a service such as GitHub, Netlify, Vercel, etc. In order to facilitate local development, `localhost` is considered a secure origin by browsers as well.

## Basic architecture

With service workers, the following steps are generally observed for basic set up:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
With service workers, the following steps are generally observed for basic set up:
With service workers, the following steps are generally observed for basic setup:

5. When the `oninstall` handler completes, the service worker is considered installed.
6. Next is activation. When the service worker is installed, it then receives an activate event. The primary use of `onactivate` is for cleanup of resources used in previous versions of a Service worker script.
7. The Service worker will now control pages, but only those opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a Service worker and maintains that for its lifetime.
1. The service worker URL is fetched and registered via [`serviceWorkerContainer.register()`](/en-US/docs/Web/API/ServiceWorkerContainer/register). If successful, the service worker is executed in a [`ServiceWorkerGlobalScope`](/en-US/docs/Web/API/ServiceWorkerGlobalScope); this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. The service worker URL is fetched and registered via [`serviceWorkerContainer.register()`](/en-US/docs/Web/API/ServiceWorkerContainer/register). If successful, the service worker is executed in a [`ServiceWorkerGlobalScope`](/en-US/docs/Web/API/ServiceWorkerGlobalScope); this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.
1. The service worker code is fetched and then registered using [`serviceWorkerContainer.register()`](/en-US/docs/Web/API/ServiceWorkerContainer/register). If successful, the service worker is executed in a [`ServiceWorkerGlobalScope`](/en-US/docs/Web/API/ServiceWorkerGlobalScope); this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.

(surely it is the file, not the URL, that is fetched)

- [Chrome](https://www.chromium.org/blink/serviceworker/service-worker-faq/)
- [Firefox](https://firefox-source-docs.mozilla.org/devtools-user/application/service_workers/index.html)
- The "Forget about this site" button, available in [Firefox's toolbar customization options](https://support.mozilla.org/en-US/kb/customize-firefox-controls-buttons-and-toolbars), can be used to clear service workers and their caches.
- [Edge](https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/service-workers/)

## See also

- [The Service Worker Cookbook](https://github.com/mdn/serviceworker-cookbook)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove this as it is unmaintained :(

@@ -481,7 +470,7 @@ When no pages are using the current version, the new worker activates and become

### Deleting old caches

You also get an `activate` event. This is generally used to do stuff that would have broken the previous version while it was still running, for example getting rid of old caches. This is also useful for removing data that is no longer needed to avoid filling up too much disk space — each browser has a hard limit on the amount of cache storage that a given service worker can use. The browser does its best to manage disk space, but it may delete the Cache storage for an origin. The browser will generally delete all of the data for an origin or none of the data for an origin.
You also get an `activate` event. This is generally used to do stuff that would have broken the previous version while it was still running, for example getting rid of old caches. This is also useful for removing data that is no longer needed to avoid filling up too much disk space — each browser has a hard limit on the amount of cache storage that a given service worker can use. The browser does its best to manage disk space, but it may delete the cache storage for an origin. The browser will generally delete all of the data for an origin or none of the data for an origin.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"You also get an activate event." reads oddly because it sounds like this is the first time we have seen this event but it isn't. Perhaps just:

Suggested change
You also get an `activate` event. This is generally used to do stuff that would have broken the previous version while it was still running, for example getting rid of old caches. This is also useful for removing data that is no longer needed to avoid filling up too much disk space — each browser has a hard limit on the amount of cache storage that a given service worker can use. The browser does its best to manage disk space, but it may delete the cache storage for an origin. The browser will generally delete all of the data for an origin or none of the data for an origin.
As we saw in the last section, when you update a service worker to a new version, you'll create a new cache in its `install` event handler. While there are open pages that are controlled by the previous version of the worker, you need to keep both caches, because the previous version needs its version of the cache.
Once all pages controlled by the old version of the worker have closed, the new service worker gets an `activate` event, and will subsequently take over control of pages. So this is the time to delete the previous cache.

? Is that correct? Too short? I thought a lot of the stuff in that para was a bit woolly tbh.

6. Next is activation. When the service worker is installed, it then receives an activate event. The primary use of `onactivate` is for cleanup of resources used in previous versions of a Service worker script.
7. The Service worker will now control pages, but only those opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a Service worker and maintains that for its lifetime.
1. The service worker URL is fetched and registered via [`serviceWorkerContainer.register()`](/en-US/docs/Web/API/ServiceWorkerContainer/register). If successful, the service worker is executed in a [`ServiceWorkerGlobalScope`](/en-US/docs/Web/API/ServiceWorkerGlobalScope); this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.
2. Installation of the worker is attempted when service worker-controlled pages are accessed subsequently. An `install` event is always the first one sent to a service worker (this can be used to start the process of populating an IndexedDB, and caching site assets). During this step, the application is preparing to make everything available for use offline.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Installation of the worker is attempted when service worker-controlled pages are accessed subsequently." is this correct? I thought installation happened as soon as the SW was downloaded and parsed (https://web.dev/learn/pwa/service-workers/#lifecycle).

Comment on lines 31 to 35
3. When the `oninstall` handler completes, the service worker is considered installed. However, it does not control the pages: pages using other service workers must be closed before it can be activated.
>**Note:** Waiting for other pages to be closed can be bypassed with [`skipWaiting()`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting).
4. Next is activation. When the service worker is installed, it then receives an `activate` event. The primary use of `onactivate` is for cleanup of resources used in previous versions of a service worker script.
5. The service worker will now control pages, but only those opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a service worker and maintains that for its lifetime.
6. Whenever a new version of a service worker is fetched, this cycle happens again and the remains of the previous version are cleaned during the new version's activation.
Copy link
Collaborator

@wbamberg wbamberg Dec 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lifecycle is for me the hardest part about service workers, and somewhere it's really worth being super clear. Maybe we could say:

Suggested change
3. When the `oninstall` handler completes, the service worker is considered installed. However, it does not control the pages: pages using other service workers must be closed before it can be activated.
>**Note:** Waiting for other pages to be closed can be bypassed with [`skipWaiting()`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting).
4. Next is activation. When the service worker is installed, it then receives an `activate` event. The primary use of `onactivate` is for cleanup of resources used in previous versions of a service worker script.
5. The service worker will now control pages, but only those opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a service worker and maintains that for its lifetime.
6. Whenever a new version of a service worker is fetched, this cycle happens again and the remains of the previous version are cleaned during the new version's activation.
3. When the `install` handler completes, the service worker is considered installed. At this point a previous version of the service worker may be active and controlling open pages. Because we don't want two different versions of the same service worker running at the same time, the new version is not yet active.
4. Once all pages controlled by the old version of the service worker have closed, it's safe to retire the old version, and the newly installed service worker receives an `activate` event. The primary use of `activate` is to clean up resources used in previous versions of the service worker.
The new service worker can call [`skipWaiting()`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting) to ask to be activated immediately without waiting for open pages to be closed. The new service worker will then receive `activate` immediately, and will take over any open pages.
5. After activation, the service worker will now control pages, but only those that were opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a service worker and maintains that for its lifetime. To override this default behavior and adopt open pages, a service worker can call [`clients.claim()`](/en-US/docs/Web/API/Clients/claim).
6. Whenever a new version of a service worker is fetched, this cycle happens again and the remains of the previous version are cleaned during the new version's activation.

does that sound right?

But I also wonder if it might be clearer to break out "first time installation" and "update" (because IMO a lot of the complexity comes from update behavior, and presenting them separately means we could build the compexity gradually...)

Comment on lines +46 to +47
- [`sync`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/sync_event)
- [`push`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/push_event)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually talk about these events (or message) here. I don't think we have to in this PR but it might be worth covering them in a follow up.

@SphinxKnight
Copy link
Member Author

Thanks a lot @wbamberg!! It is far better now :) #simple #easily

Copy link
Collaborator

@wbamberg wbamberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @SphinxKnight for this update! This important page has made me sad for a long time but I never got around to updating it.

@wbamberg wbamberg merged commit 571d6b9 into mdn:main Dec 17, 2022
SphinxKnight added a commit to SphinxKnight/translated-content that referenced this pull request Dec 18, 2022
cw118 added a commit to mdn/translated-content that referenced this pull request Dec 22, 2022
* WIP3

* First page

* First pass

* Parity with mdn/content#22682

* fix md typo

* Small typofixes and updates/nitpicking

Co-authored-by: cw118 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content:WebAPI Web API docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants