5 lines
25 KiB
JSON
5 lines
25 KiB
JSON
{
|
|
"id": "guide/service-worker-devops",
|
|
"title": "Service worker in production",
|
|
"contents": "\n\n\n<div class=\"github-links\">\n <a href=\"https://github.com/angular/angular/edit/master/aio/content/guide/service-worker-devops.md?message=docs%3A%20describe%20your%20change...\" aria-label=\"Suggest Edits\" title=\"Suggest Edits\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">mode_edit</i></a>\n</div>\n\n\n<div class=\"content\">\n <h1 id=\"service-worker-in-production\">Service worker in production<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#service-worker-in-production\"><i class=\"material-icons\">link</i></a></h1>\n<p>This page is a reference for deploying and supporting production apps that use the Angular service worker. It explains how the Angular service worker fits into the larger production environment, the service worker's behavior under various conditions, and available resources and fail-safes.</p>\n<h4 id=\"prerequisites\">Prerequisites<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#prerequisites\"><i class=\"material-icons\">link</i></a></h4>\n<p>A basic understanding of the following:</p>\n<ul>\n<li><a href=\"guide/service-worker-communications\">Service Worker Communication</a>.</li>\n</ul>\n<h2 id=\"service-worker-and-caching-of-app-resources\">Service worker and caching of app resources<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#service-worker-and-caching-of-app-resources\"><i class=\"material-icons\">link</i></a></h2>\n<p>Conceptually, you can imagine the Angular service worker as a forward cache or a CDN edge that is installed in the end user's web browser. The service worker's job is to satisfy requests made by the Angular app for resources or data from a local cache, without needing to wait for the network. Like any cache, it has rules for how content is expired and updated.</p>\n<a id=\"versions\"></a>\n<h3 id=\"app-versions\">App versions<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#app-versions\"><i class=\"material-icons\">link</i></a></h3>\n<p>In the context of an Angular service worker, a \"version\" is a collection of resources that represent a specific build of the Angular app. Whenever a new build of the app is deployed, the service worker treats that build as a new version of the app. This is true even if only a single file is updated. At any given time, the service worker may have multiple versions of the app in its cache and it may be serving them simultaneously. For more information, see the <a href=\"guide/service-worker-devops#tabs\">App tabs</a> section below.</p>\n<p>To preserve app integrity, the Angular service worker groups all files into a version together. The files grouped into a version usually include HTML, JS, and CSS files. Grouping of these files is essential for integrity because HTML, JS, and CSS files frequently refer to each other and depend on specific content. For example, an <code>index.html</code> file might have a <code><script></code> tag that references <code>bundle.js</code> and it might attempt to call a function <code>startApp()</code> from within that script. Any time this version of <code>index.html</code> is served, the corresponding <code>bundle.js</code> must be served with it. For example, assume that the <code>startApp()</code> function is renamed to <code>runApp()</code> in both files. In this scenario, it is not valid to serve the old <code>index.html</code>, which calls <code>startApp()</code>, along with the new bundle, which defines <code>runApp()</code>.</p>\n<p>This file integrity is especially important when lazy loading modules.\nA JS bundle may reference many lazy chunks, and the filenames of the\nlazy chunks are unique to the particular build of the app. If a running\napp at version <code>X</code> attempts to load a lazy chunk, but the server has\nupdated to version <code>X + 1</code> already, the lazy loading operation will fail.</p>\n<p>The version identifier of the app is determined by the contents of all\nresources, and it changes if any of them change. In practice, the version\nis determined by the contents of the <code>ngsw.json</code> file, which includes\nhashes for all known content. If any of the cached files change, the file's\nhash will change in <code>ngsw.json</code>, causing the Angular service worker to\ntreat the active set of files as a new version.</p>\n<p>With the versioning behavior of the Angular service worker, an application\nserver can ensure that the Angular app always has a consistent set of files.</p>\n<h4 id=\"update-checks\">Update checks<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#update-checks\"><i class=\"material-icons\">link</i></a></h4>\n<p>Every time the user opens or refreshes the application, the Angular service worker\nchecks for updates to the app by looking for updates to the <code>ngsw.json</code> manifest. If\nan update is found, it is downloaded and cached automatically, and will be served\nthe next time the application is loaded.</p>\n<h3 id=\"resource-integrity\">Resource integrity<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#resource-integrity\"><i class=\"material-icons\">link</i></a></h3>\n<p>One of the potential side effects of long caching is inadvertently\ncaching an invalid resource. In a normal HTTP cache, a hard refresh\nor cache expiration limits the negative effects of caching an invalid\nfile. A service worker ignores such constraints and effectively long\ncaches the entire app. Consequently, it is essential that the service worker\ngets the correct content.</p>\n<p>To ensure resource integrity, the Angular service worker validates\nthe hashes of all resources for which it has a hash. Typically for\nan app created with the <a href=\"cli\">Angular CLI</a>, this is everything in the <code>dist</code> directory covered by\nthe user's <code>src/ngsw-config.json</code> configuration.</p>\n<p>If a particular file fails validation, the Angular service worker\nattempts to re-fetch the content using a \"cache-busting\" URL\nparameter to eliminate the effects of browser or intermediate\ncaching. If that content also fails validation, the service worker\nconsiders the entire version of the app to be invalid and it stops\nserving the app. If necessary, the service worker enters a safe mode\nwhere requests fall back on the network, opting not to use its cache\nif the risk of serving invalid, broken, or outdated content is high.</p>\n<p>Hash mismatches can occur for a variety of reasons:</p>\n<ul>\n<li>Caching layers in between the origin server and the end user could serve stale content.</li>\n<li>A non-atomic deployment could result in the Angular service worker having visibility of partially updated content.</li>\n<li>Errors during the build process could result in updated resources without <code>ngsw.json</code> being updated. The reverse could also happen resulting in an updated <code>ngsw.json</code> without updated resources.</li>\n</ul>\n<h4 id=\"unhashed-content\">Unhashed content<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#unhashed-content\"><i class=\"material-icons\">link</i></a></h4>\n<p>The only resources that have hashes in the <code>ngsw.json</code>\nmanifest are resources that were present in the <code>dist</code>\ndirectory at the time the manifest was built. Other\nresources, especially those loaded from CDNs, have\ncontent that is unknown at build time or are updated\nmore frequently than the app is deployed.</p>\n<p>If the Angular service worker does not have a hash to validate\na given resource, it still caches its contents but it honors\nthe HTTP caching headers by using a policy of \"stale while\nrevalidate.\" That is, when HTTP caching headers for a cached\nresource indicate that the resource has expired, the Angular\nservice worker continues to serve the content and it attempts\nto refresh the resource in the background. This way, broken\nunhashed resources do not remain in the cache beyond their\nconfigured lifetimes.</p>\n<a id=\"tabs\"></a>\n<h3 id=\"app-tabs\">App tabs<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#app-tabs\"><i class=\"material-icons\">link</i></a></h3>\n<p>It can be problematic for an app if the version of resources\nit's receiving changes suddenly or without warning. See the\n<a href=\"guide/service-worker-devops#versions\">Versions</a> section above\nfor a description of such issues.</p>\n<p>The Angular service worker provides a guarantee: a running app\nwill continue to run the same version of the app. If another\ninstance of the app is opened in a new web browser tab, then\nthe most current version of the app is served. As a result,\nthat new tab can be running a different version of the app\nthan the original tab.</p>\n<p>It's important to note that this guarantee is <strong>stronger</strong>\nthan that provided by the normal web deployment model. Without\na service worker, there is no guarantee that code lazily loaded\nlater in a running app is from the same version as the initial\ncode for the app.</p>\n<p>There are a few limited reasons why the Angular service worker\nmight change the version of a running app. Some of them are\nerror conditions:</p>\n<ul>\n<li>The current version becomes invalid due to a failed hash.</li>\n<li>An unrelated error causes the service worker to enter safe mode; that is, temporary deactivation.</li>\n</ul>\n<p>The Angular service worker is aware of which versions are in\nuse at any given moment and it cleans up versions when\nno tab is using them.</p>\n<p>Other reasons the Angular service worker might change the version\nof a running app are normal events:</p>\n<ul>\n<li>The page is reloaded/refreshed.</li>\n<li>The page requests an update be immediately activated via the <code><a href=\"api/service-worker/SwUpdate\" class=\"code-anchor\">SwUpdate</a></code> service.</li>\n</ul>\n<h3 id=\"service-worker-updates\">Service worker updates<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#service-worker-updates\"><i class=\"material-icons\">link</i></a></h3>\n<p>The Angular service worker is a small script that runs in web browsers.\nFrom time to time, the service worker will be updated with bug\nfixes and feature improvements.</p>\n<p>The Angular service worker is downloaded when the app is first opened\nand when the app is accessed after a period of inactivity. If the\nservice worker has changed, the service worker will be updated in the background.</p>\n<p>Most updates to the Angular service worker are transparent to the\napp—the old caches are still valid and content is still served\nnormally. However, occasionally a bugfix or feature in the Angular\nservice worker requires the invalidation of old caches. In this case,\nthe app will be refreshed transparently from the network.</p>\n<h3 id=\"bypassing-the-service-worker\">Bypassing the service worker<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#bypassing-the-service-worker\"><i class=\"material-icons\">link</i></a></h3>\n<p>In some cases, you may want to bypass the service worker entirely and let the browser handle the\nrequest instead. An example is when you rely on a feature that is currently not supported in service\nworkers (e.g.\n<a href=\"https://github.com/w3c/ServiceWorker/issues/1141\">reporting progress on uploaded files</a>).</p>\n<p>To bypass the service worker you can set <code>ngsw-bypass</code> as a request header, or as a query parameter.\n(The value of the header or query parameter is ignored and can be empty or omitted.)</p>\n<h2 id=\"debugging-the-angular-service-worker\">Debugging the Angular service worker<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#debugging-the-angular-service-worker\"><i class=\"material-icons\">link</i></a></h2>\n<p>Occasionally, it may be necessary to examine the Angular service\nworker in a running state to investigate issues or to ensure that\nit is operating as designed. Browsers provide built-in tools for\ndebugging service workers and the Angular service worker itself\nincludes useful debugging features.</p>\n<h3 id=\"locating-and-analyzing-debugging-information\">Locating and analyzing debugging information<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#locating-and-analyzing-debugging-information\"><i class=\"material-icons\">link</i></a></h3>\n<p>The Angular service worker exposes debugging information under\nthe <code>ngsw/</code> virtual directory. Currently, the single exposed URL\nis <code>ngsw/<a href=\"api/animations/state\" class=\"code-anchor\">state</a></code>. Here is an example of this debug page's contents:</p>\n<code-example>\nNGSW Debug Info:\n\nDriver <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: NORMAL ((nominal))\nLatest manifest hash: eea7f5f464f90789b621170af5a569d6be077e5c\nLast update check: never\n\n=== <a href=\"api/core/Version\" class=\"code-anchor\">Version</a> eea7f5f464f90789b621170af5a569d6be077e5c ===\n\nClients: 7b79a015-69af-4d3d-9ae6-95ba90c79486, 5bc08295-aaf2-42f3-a4cc-9e4ef9100f65\n\n=== Idle Task Queue ===\nLast update <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>: 1s496u\nLast update run: never\nTask queue:\n * init post-load (update, cleanup)\n\nDebug log:\n</code-example>\n<h4 id=\"driver-state\">Driver state<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#driver-state\"><i class=\"material-icons\">link</i></a></h4>\n<p>The first line indicates the driver state:</p>\n<code-example>\nDriver <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: NORMAL ((nominal))\n</code-example>\n<p><code>NORMAL</code> indicates that the service worker is operating normally and is not in a degraded state.</p>\n<p>There are two possible degraded states:</p>\n<ul>\n<li>\n<p><code>EXISTING_CLIENTS_ONLY</code>: the service worker does not have a\nclean copy of the latest known version of the app. Older cached\nversions are safe to use, so existing tabs continue to run from\ncache, but new loads of the app will be served from the network.\nThe service worker will try to recover from this state when a new\nversion of the application is detected and installed (that is,\nwhen a new <code>ngsw.json</code> is available).</p>\n</li>\n<li>\n<p><code>SAFE_MODE</code>: the service worker cannot guarantee the safety of\nusing cached data. Either an unexpected error occurred or all\ncached versions are invalid. All traffic will be served from the\nnetwork, running as little service worker code as possible.</p>\n</li>\n</ul>\n<p>In both cases, the parenthetical annotation provides the\nerror that caused the service worker to enter the degraded state.</p>\n<p>Both states are temporary; they are saved only for the lifetime of the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope\">ServiceWorker\ninstance</a>.\nThe browser sometimes terminates an idle service worker to conserve memory and\nprocessor power, and creates a new service worker instance in response to\nnetwork events. The new instance starts in the <code>NORMAL</code> mode, regardless of the\nstate of the previous instance.</p>\n<h4 id=\"latest-manifest-hash\">Latest manifest hash<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#latest-manifest-hash\"><i class=\"material-icons\">link</i></a></h4>\n<code-example>\nLatest manifest hash: eea7f5f464f90789b621170af5a569d6be077e5c\n</code-example>\n<p>This is the SHA1 hash of the most up-to-date version of the app that the service worker knows about.</p>\n<h4 id=\"last-update-check\">Last update check<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#last-update-check\"><i class=\"material-icons\">link</i></a></h4>\n<code-example>\nLast update check: never\n</code-example>\n<p>This indicates the last time the service worker checked for a new version, or update, of the app. <code>never</code> indicates that the service worker has never checked for an update.</p>\n<p>In this example debug file, the update check is currently scheduled, as explained the next section.</p>\n<h4 id=\"version\">Version<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#version\"><i class=\"material-icons\">link</i></a></h4>\n<code-example>\n=== <a href=\"api/core/Version\" class=\"code-anchor\">Version</a> eea7f5f464f90789b621170af5a569d6be077e5c ===\n\nClients: 7b79a015-69af-4d3d-9ae6-95ba90c79486, 5bc08295-aaf2-42f3-a4cc-9e4ef9100f65\n</code-example>\n<p>In this example, the service worker has one version of the app cached and\nbeing used to serve two different tabs. Note that this version hash\nis the \"latest manifest hash\" listed above. Both clients are on the\nlatest version. Each client is listed by its ID from the <code>Clients</code>\nAPI in the browser.</p>\n<h4 id=\"idle-task-queue\">Idle task queue<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#idle-task-queue\"><i class=\"material-icons\">link</i></a></h4>\n<code-example>\n=== Idle Task Queue ===\nLast update <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>: 1s496u\nLast update run: never\nTask queue:\n * init post-load (update, cleanup)\n</code-example>\n<p>The Idle Task Queue is the queue of all pending tasks that happen\nin the background in the service worker. If there are any tasks\nin the queue, they are listed with a description. In this example,\nthe service worker has one such task scheduled, a post-initialization\noperation involving an update check and cleanup of stale caches.</p>\n<p>The last update tick/run counters give the time since specific\nevents happened related to the idle queue. The \"Last update run\"\ncounter shows the last time idle tasks were actually executed.\n\"Last update tick\" shows the time since the last event after\nwhich the queue might be processed.</p>\n<h4 id=\"debug-log\">Debug log<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#debug-log\"><i class=\"material-icons\">link</i></a></h4>\n<code-example>\nDebug log:\n</code-example>\n<p>Errors that occur within the service worker will be logged here.</p>\n<h3 id=\"developer-tools\">Developer Tools<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#developer-tools\"><i class=\"material-icons\">link</i></a></h3>\n<p>Browsers such as Chrome provide developer tools for interacting\nwith service workers. Such tools can be powerful when used properly,\nbut there are a few things to keep in mind.</p>\n<ul>\n<li>\n<p>When using developer tools, the service worker is kept running\nin the background and never restarts. This can cause behavior with Dev\nTools open to differ from behavior a user might experience.</p>\n</li>\n<li>\n<p>If you look in the Cache Storage viewer, the cache is frequently\nout of date. Right click the Cache Storage title and refresh the caches.</p>\n</li>\n</ul>\n<p>Stopping and starting the service worker in the Service Worker\npane triggers a check for updates.</p>\n<h2 id=\"service-worker-safety\">Service Worker Safety<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#service-worker-safety\"><i class=\"material-icons\">link</i></a></h2>\n<p>Like any complex system, bugs or broken configurations can cause\nthe Angular service worker to act in unforeseen ways. While its\ndesign attempts to minimize the impact of such problems, the\nAngular service worker contains several failsafe mechanisms in case\nan administrator ever needs to deactivate the service worker quickly.</p>\n<h3 id=\"fail-safe\">Fail-safe<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#fail-safe\"><i class=\"material-icons\">link</i></a></h3>\n<p>To deactivate the service worker, remove or rename the\n<code>ngsw.json</code> file. When the service worker's request\nfor <code>ngsw.json</code> returns a <code>404</code>, then the service worker\nremoves all of its caches and de-registers itself,\nessentially self-destructing.</p>\n<h3 id=\"safety-worker\">Safety Worker<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#safety-worker\"><i class=\"material-icons\">link</i></a></h3>\n<p>Also included in the <code>@angular/service-worker</code> NPM package is a small\nscript <code>safety-worker.js</code>, which when loaded will unregister itself\nfrom the browser. This script can be used as a last resort to get rid\nof unwanted service workers already installed on client pages.</p>\n<p>It's important to note that you cannot register this worker directly,\nas old clients with cached state may not see a new <code>index.html</code> which\ninstalls the different worker script. Instead, you must serve the\ncontents of <code>safety-worker.js</code> at the URL of the Service Worker script\nyou are trying to unregister, and must continue to do so until you are\ncertain all users have successfully unregistered the old worker. For\nmost sites, this means that you should serve the safety worker at the\nold Service Worker URL forever.</p>\n<p>This script can be used both to deactivate <code>@angular/service-worker</code>\nas well as any other Service Workers which might have been served in\nthe past on your site.</p>\n<h3 id=\"changing-your-apps-location\">Changing your app's location<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#changing-your-apps-location\"><i class=\"material-icons\">link</i></a></h3>\n<p>It is important to note that service workers don't work behind redirect. You\nmay have already encountered the error <code>The script resource is behind a redirect, which is disallowed</code>.</p>\n<p>This can be a problem if you have to change your app's location. If you setup\na redirect from the old location (for example <code>example.com</code>) to the new\nlocation (for example <code>www.example.com</code>) the worker will stop working.\nAlso, the redirect won't even trigger for users who are loading the site\nentirely from Service Worker. The old worker (registered at <code>example.com</code>)\ntries to update and sends requests to the old location <code>example.com</code> which\nget redirected to the new location <code>www.example.com</code> and create the error\n<code>The script resource is behind a redirect, which is disallowed</code>.</p>\n<p>To remedy this, you may need to kill the old worker using one of the above\ntechniques (<a href=\"guide/service-worker-devops#fail-safe\">Fail-safe</a> or <a href=\"guide/service-worker-devops#safety-worker\">Safety Worker</a>).</p>\n<h2 id=\"more-on-angular-service-workers\">More on Angular service workers<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/service-worker-devops#more-on-angular-service-workers\"><i class=\"material-icons\">link</i></a></h2>\n<p>You may also be interested in the following:</p>\n<ul>\n<li><a href=\"guide/service-worker-config\">Service Worker Configuration</a>.</li>\n</ul>\n\n \n</div>\n\n<!-- links to this doc:\n - guide/service-worker-communications\n - guide/service-worker-config\n - guide/service-worker-intro\n-->\n<!-- links from this doc:\n - api/animations/state\n - api/core/Version\n - api/core/testing/tick\n - api/service-worker/SwUpdate\n - cli\n - guide/service-worker-communications\n - guide/service-worker-config\n - guide/service-worker-devops#app-tabs\n - guide/service-worker-devops#app-versions\n - guide/service-worker-devops#bypassing-the-service-worker\n - guide/service-worker-devops#changing-your-apps-location\n - guide/service-worker-devops#debug-log\n - guide/service-worker-devops#debugging-the-angular-service-worker\n - guide/service-worker-devops#developer-tools\n - guide/service-worker-devops#driver-state\n - guide/service-worker-devops#fail-safe\n - guide/service-worker-devops#idle-task-queue\n - guide/service-worker-devops#last-update-check\n - guide/service-worker-devops#latest-manifest-hash\n - guide/service-worker-devops#locating-and-analyzing-debugging-information\n - guide/service-worker-devops#more-on-angular-service-workers\n - guide/service-worker-devops#prerequisites\n - guide/service-worker-devops#resource-integrity\n - guide/service-worker-devops#safety-worker\n - guide/service-worker-devops#service-worker-and-caching-of-app-resources\n - guide/service-worker-devops#service-worker-in-production\n - guide/service-worker-devops#service-worker-safety\n - guide/service-worker-devops#service-worker-updates\n - guide/service-worker-devops#tabs\n - guide/service-worker-devops#unhashed-content\n - guide/service-worker-devops#update-checks\n - guide/service-worker-devops#version\n - guide/service-worker-devops#versions\n - https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope\n - https://github.com/angular/angular/edit/master/aio/content/guide/service-worker-devops.md?message=docs%3A%20describe%20your%20change...\n - https://github.com/w3c/ServiceWorker/issues/1141\n-->"
|
|
} |