├── CNAME
├── README.md
├── game
└── README.md
├── magazines-app
└── README.md
├── maps
└── README.md
├── podcast-app
└── README.md
├── todo-app
├── README.md
├── cdn.example.com
│ ├── all-v1.css
│ └── all-v1.js
└── example.com
│ ├── ctrl.js
│ └── index.html
├── twitter-client
└── README.md
└── wiki
├── README.md
├── cdn.example.com
├── all-v1.css
└── all-v1.js
└── example.com
├── ctrl.js
└── index.html
/CNAME:
--------------------------------------------------------------------------------
1 | examples.serviceworker.org
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # THIS REPO IS NO LONGER MAINTAINED
2 |
3 | Thanks for stopping by! When we started this work, Service Workers were just becoming "a thing" - so this repo was intended to bootstrap the ecosystem. Since then countless amazing resources and videos on using Service Workers became available. As such, we are no longer able to keep up. Below links are still relevant, but we are not longer adding new ones.
4 |
5 | ## Historical...
6 |
7 | We hope to build a set of reference applications that make full use of [service workers](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html). However, currently there are no working demos in this repo.
8 |
9 | ## For ServiceWorker demos try out:
10 |
11 | ### Service Worker recipes
12 |
13 | - [Basic registration](https://googlechrome.github.io/samples/service-worker/registration/index.html) -
14 | a bare-bones sample that simply performs service worker registration, with placeholders for various event handlers.
15 | - [Detailed registration](https://googlechrome.github.io/samples/service-worker/registration-events/index.html) -
16 | a sample that provides detailed information about the service worker registration and the state changes that a
17 | service worker undergoes.
18 | - [Prefetching resources during installation](https://googlechrome.github.io/samples/service-worker/prefetch/index.html) -
19 | a sample demonstrating how to prefetch and cache a list of URLs during the service worker's installation, ensuring that they're
20 | available offline.
21 | - [Selective caching](https://googlechrome.github.io/samples/service-worker/selective-caching/index.html) -
22 | a sample of how a service worker can cache resources "on the fly", assuming the resources meet certain criteria (MIME type,
23 | domain, etc.).
24 | - [Read-through caching](https://googlechrome.github.io/samples/service-worker/read-through-caching/index.html) -
25 | a sample of caching _all_ resources that are requested "on the fly", unconditionally.
26 | - [Offline Google Analytics](https://googlechrome.github.io/samples/service-worker/offline-analytics/index.html) -
27 | extends the [read-through caching](https://googlechrome.github.io/samples/service-worker/read-through-caching/index.html) example to add in support for "replaying" failed Google Analytics pings, allowing pages to submit Google Analytics data associated with offline/cached page views.
28 | - [Fallback responses](https://googlechrome.github.io/samples/service-worker/fallback-response/index.html) -
29 | a sample illustrating how you can return alternative "fallback" content if an initial fetch request fails.
30 | - [Mock responses](https://googlechrome.github.io/samples/service-worker/mock-responses/index.html) -
31 | a sample illustrating how you can return content created on the fly in response to a page's requests.
32 | - [Using `postMessage`](https://googlechrome.github.io/samples/service-worker/post-message/index.html) -
33 | a sample illustrating the use of `postMessage()` to send commands from a controlled page to its service worker, giving the page control over the cache.
34 |
35 |
36 | ### Basic Demos
37 | * [Wiki engine demo](https://github.com/sandropaganotti/service-worker-wiki)
38 | * [isserviceworkerready spec tests](https://github.com/jakearchibald/isserviceworkerready/tree/master/src/demos)
39 | * [Cache All](https://github.com/boopathi/sw-cache-all) - The bare minimum Service Worker to cache all requests from the app.
40 |
41 | ### Substantial demos
42 | * [Offline News](https://github.com/jakearchibald/offline-news-service-worker)
43 | * [Trained to Thrill](https://github.com/jakearchibald/trained-to-thrill)
44 | * [Tweetdeck offline](https://github.com/jakearchibald/tweetdeck-prototype)
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ## This repo is just getting started
54 | All the code in this repo is in the earliest stage of development. We are looking for people to help us create these apps!
55 |
56 | Our goal is to show how you can perform tasks that are common in native applications using this new set of APIs. We want to keep the apps simple, so they can be easily bisected and copied by anyone.
57 |
58 | **Please note that the spec and implementations are in a very early stage!** You may find issues with implementations in that they may often change or produce strange results at first. :
59 |
60 | **To see what actually works in browsers today, see Jake Archibald's [IsServiceWorkerReady](https://jakearchibald.github.io/isserviceworkerready/) page.**
61 |
62 | ### How can you help?
63 | The process below is a guideline to how to get started.
64 |
65 | 1. Fork this repo!
66 | 1. Choose one of the apps from the directories above.
67 | 1. Use the app's behavior draft to implement the application.
68 | 1. Keep it really simple! See our list of resources below to learn about service workers.
69 |
70 | ## How to run these things?
71 | We will be hosting them on a website soon, so you can see them as we build them.
72 |
73 | Right now, you will need:
74 |
75 | * [Chrome](https://www.google.com/chrome/browser/desktop/index.html).
76 | * [Opera](http://www.opera.com/pl/computer/windows).
77 | * [Firefox Nightly](https://nightly.mozilla.org/).
78 |
79 | ## Wanna build something different?
80 | If you have a more interesting app you want to build, please add them to this repo. Just add a directory to the root directory with a README.md file explaining what the app does and send us a pull request!
81 |
82 | ##Resources
83 |
84 | * [The specification](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html).
85 |
86 | ### Articles/Vidoes
87 |
88 | * [ServiceWorkers and Firefox](https://hacks.mozilla.org/2014/06/serviceworkers-and-firefox/) - Introduction to ServiceWorkers on Firefox!
89 | * [Service Worker - first draft published](http://jakearchibald.com/2014/service-worker-first-draft/) - Introduction and tutorial including code snippets!
90 | * [Video: The ServiceWorker: The network layer is yours to own](https://www.youtube.com/watch?v=4uQMl7mFB6g) - video introducing ServiceWorker including HTTP caching, request, and showing SW in forms, the basis for push messaging, alarms, geofencing and background sync.
91 |
92 | ### Debugging
93 |
94 | * ServiceWorkerInternals (chrome canary only - chrome://serviceworker-internals/) - page for debugging ServiceWorkers in chrome, including stopping, unregistering and starting workers.
95 |
96 | ### Examples
97 |
98 | * [Jake Archibald's Trained to Thrill](https://jakearchibald.github.io/trained-to-thrill/) - Jake made a great demo app which pulls in images from Flickr, uses fetch, uses cache (not implemented yet) and worker registrations.
99 | * [Simple ServiceWorker](https://github.com/matthew-andrews/serviceworker-simple) - A simple Service Worker example by Matt Andrews.
100 |
101 | ### Related APIs
102 |
103 | * [Promises HTML5Rocks](http://www.html5rocks.com/en/tutorials/es6/promises/) - Understanding Promises (used frequently in ServiceWorkers especially in fetch, cache).
104 | * [The Basics of Web Workers](http://www.html5rocks.com/en/tutorials/workers/basics/) - Understanding concurrency in JavaScript and how web workers work.
105 |
106 |
107 |
--------------------------------------------------------------------------------
/game/README.md:
--------------------------------------------------------------------------------
1 | ## Game with independently caching levels
2 |
3 | This ServiceWorker web app demo will be a game where each level is a different cache group.
4 |
5 | You can go ahead and do this however you wish; a good example would be a 2D platformer based on levels. Each level could have it's own ServiceWorker cache, when a user is visiting the app levels are cached in separate caches (maybe the next 2/3 levels?) which will then be ready for them to load and play as soon as they complete the previous level.
6 |
7 | ## More Information / Requirements
8 |
9 | * User visited page that was cached in a ServiceWorker cache, the site decides to show them the cached data straight away for performance, then update with fresh data when/if it arrives.
10 |
11 | * User visits game’s url
12 | * If first visit
13 | * Loading screen delivered (as normal html)
14 | * Assets for menu screens and non-level specific behaviour (physics engine etc) downloaded and cached
15 | * If any request fails, error message (not browser UI) shown to user
16 | * Menu screen shown (using cached assets)
17 | * Send versions of game logic / menus & each cached level to server, server returns items that are out of date
18 | * if fail, abort these steps
19 | * If game logic / menus are out of date
20 | * Fetch new assets
21 | * If any request fails, do not cache, abort these steps
22 | * Once all assets are fetched, cache’em
23 | * for each out of date level, delete from cache
24 | * For each undownloaded level (with priority to earlier levels)
25 | * Download some kind of manifest for level, containing version, level structure and additional assets required
26 | * Request any additional resources indicated by manifest
27 | * Once the manifest and all resources have downloaded, commit to cache
28 | * If any request fails, do not cache, fail silently
29 | * User clicks “play”
30 | * Level select screen fetched from cache and shown
31 | * Download progress/success/failure of levels indicated
32 | * User clicks on level whose download has failed or in progress
33 | * See “Starting uncached level”
34 | * User clicks on cached level
35 | * See “Starting cached level”
36 | * Starting uncached level
37 | * Show loading screen
38 | * Restart download if failed
39 | * Download level data & cache as specified earlier (see “For each undownloaded level”)
40 | * If succeed
41 | * See “Starting cached level”
42 | * Else
43 | * Show reason as error message
44 | * Starting cached level
45 | * Load level from cache & begin having fun
46 | * On level complete
47 | * If next level cached
48 | * See “Starting cached level”
49 | * Else
50 | * See “Starting uncached level”
51 |
52 | ### Special Requirement
53 | In this demo we have a special requirement for those of you who want to do something extra: one of the levels should go through an 'update'. The expected behaviour is the user should only be able to play an 'updated' level when 100% of the level has been cached. Of course it will be difficult for us to replicate this, so please go through the experience and just document the results as a .md file!
54 |
55 | ### Questions
56 | If you have questions please ask them in the issues. Just start a new issue with your question.
57 |
--------------------------------------------------------------------------------
/magazines-app/README.md:
--------------------------------------------------------------------------------
1 | ## Magazine app
2 |
3 | This ServiceWorker demo webapp will allow a user to view a magazine app when offline, and gain some performance benefits by pulling the 'shell' of the app from a ServiceWorker cache. This should show how ServceWorker can be used to get fresh content from a server as a form of a bundle. Here are some detailed requirements:
4 |
5 | * The magazine app 'shell' is held within a ServiceWorker cache
6 | * Some content is also held in a ServiceWorker cache or IndexedDB (this content was originally pulled from a server and displayed to the user on a previous session)
7 | * the app would first try to pull new content from the server
8 | * if succesful display to the user
9 | * if unsuccessful the app takes the last piece of content from another ServiceWorker cache *or* from other storage and displays this instead.
10 |
11 | The user may benefit from some message to say "you have the most up to date content" (or something similar and less wordy!). In this demo you should [1] register a ServiceWorker, [2] add the 'shell' into one ServiceWorker cache [3] add some content into another ServiceWorker cache, [3] use fetching to get content from the cache or server depending on whether a connection to the server was successful.
12 |
13 | ### Cache Age
14 | If the user is viewing a page which was served by a ServiceWorker cache, the user should be aware that a particular page is 30 days old and some data may not be relevant.
15 |
16 | ### Webfonts
17 | If the page uses webfonts we want to cache web font formats used without having to cache other suggested formats. Eg, cache WOFF or TTF, not both (similar cases for media-query determined imagery).
18 |
19 | ### Questions
20 | If you have questions please ask them in the issues. Just start a new issue with your question.
21 |
--------------------------------------------------------------------------------
/maps/README.md:
--------------------------------------------------------------------------------
1 | ## Maps
2 |
3 | This ServiceWorker demo webapp downloads/caches maps for later use. Users often use mapping web apps when on the move. In many cases they use these apps when they are in areas of bad or no connection. In this case a user would be able to download/cache a section of a map (maybe when they are at on their home wifi before leaving) and use this map later.
4 |
5 | For this demo webapp you will need to [1] register a ServiceWorker, [2] when a user vists a map when online this map gets 'cached' in a ServiceWorker cache, [3] use 'fetches' to get the map from the cache rather than the server when a user next vists the cached area on the map.
6 |
7 | ### More Information / Requirements
8 | Please go ahead and make the app using the brief requirements above! If you want more details requirements see below:
9 |
10 | **Zoom Levels**
11 |
12 | Need to consider what zoom levels of the map need to be downloaded including the zoom level the user is on.
13 | * It may make more sense that all zoom levels from the most granular the user is using and up is downloaded, rather then all levels.
14 | * EXAMPLE: (zoom levels 1-10) This means that if a user is viewing zoom level 5 (medium level of granularity) and they can see the whole of the UK then levels 5-10 will be downloaded (10 will be the whole Earth view). The user will not be able to zoom to levels 4,3,2,1 when offline as they did not visit these online.
15 | * This method helps to make sure in the instance when a user views the whole earth they also don’t accidently download all maps at all zoom levels
16 |
17 | **Update**
18 |
19 | One of the benefits of the web is the fact that the user always (or almost always) sees the most up to date version of any web-app or web-site. When we start introducing complex caching methods the issue arises of when a web-app’s assets have been updated then how does a “cached” web app know this has happened?
20 |
21 | In this use case the user should be able to know that they are seeing a cached version of the map, and should see an option to redownload a more up-to-date version. User should then also be informed of any updates to the page if one occured.
22 |
23 | ### Questions
24 | If you have questions please ask them in the issues. Just start a new issue with your question.
25 |
--------------------------------------------------------------------------------
/podcast-app/README.md:
--------------------------------------------------------------------------------
1 | ## A Simple Podcast Subscription / Listening Webapp
2 |
3 | This ServiceWorker demo webapp would allow users to subscribe to a set of podcasts via RSS. It would then periodically check these RSS feeds for new episodes and sync new episodes to local storage to enable offline listening.
4 |
5 | For this app you will need to [1] register a ServiceWorker, [2] get podcasts via XHR whilst running the in background (maybe as a inactive tab?), [3] save podcasts in a ServiceWorker cache and [4] detect 'fetches' to get podcasts from the cache rather than from a server.
6 |
7 | ### More Information
8 | Please go ahead and make the app to the brief requirements given above! If you want more in detail requirements please see below. The app should:
9 |
10 | - display a menu of available podcasts
11 | - allow user to subscribe to podcasts from the menu or by entering in an RSS feed URL
12 | - pull down RSS feeds when online
13 | - determine if there are new items listed
14 | - download new items if online
15 | - queue for later download if offline
16 | - periodically check if offline or online and download queued files when online
17 | - know when the user is on wifi as opposed to cellular coverage and prompt "are you sure" before downloading over cellular
18 | - allow user to choose podcasts to play from menu generated from RSS feed data
19 | - indicate to user which episodes are unplayed
20 | - mark episodes as played when user plays them
21 | - remove played items from local storage after a configured period of time
22 | - allow user to view and delete episodes
23 |
24 | ### Questions
25 | If you have questions please ask them in the issues. Just start a new issue with your question.
26 |
--------------------------------------------------------------------------------
/todo-app/README.md:
--------------------------------------------------------------------------------
1 | ## Todo App (a single page app)
2 |
3 | This ServiceWorker demo app makes a simple to-do app work in an offline mode. AppCache was great at doing things like this, so we're particularly interested in making sure ServiceWorker is just as useful for these use cases! More details below:
4 |
5 | ### More Details
6 | First of all, create a basic web-based todo app; it can follow a framework, be one you made earlier, or made from scratch. Then, use ServiceWorker to get the following use cases worker:
7 |
8 | * User visits todo app
9 | * If the app is cached
10 | * Fetch from cache
11 | * Check for updated application
12 | * If update found / no cache exists
13 | * Download new resources
14 | * Once all downloaded successfully
15 | * Clear cache
16 | * Add downloaded content to cache
17 | * If “interacted with”
18 | * Show “Update available” message
19 | * Else
20 | * Refresh page
21 | * Else
22 | * Deliver page and resources normally
23 | * Once all resources are successfully download, add to cache
24 | * On UI interaction (changing the state of the page)
25 | * Mark page as “interacted with”
26 |
27 | For this app you will need to [1] register a ServiceWorker [2] detect fetches to see when the app is loaded [3] use the ServiceWorker cache to load into and from.
28 |
29 | ### Questions
30 | If you have questions please ask them in the issues. Just start a new issue with your question.
31 |
--------------------------------------------------------------------------------
/todo-app/cdn.example.com/all-v1.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'whatever';
3 | src: url('whatever-v1.woff') format('woff');
4 | }
5 |
6 | html {
7 | background: url('whatever-v1.png');
8 | }
9 |
10 | /*
11 | Using device-width intentionally, hoping we find a way
12 | just to take one of these files offline
13 | */
14 | @media screen and (min-device-width: 500px) {
15 | html {
16 | background: url('whatever-large-v1.png');
17 | }
18 | }
--------------------------------------------------------------------------------
/todo-app/cdn.example.com/all-v1.js:
--------------------------------------------------------------------------------
1 | // set up the controller
2 | if (navigator.registerServiceWorker) {
3 | navigator.registerServiceWorker("/*", "/ctrl.js");
4 |
5 | navigator.addEventListener('serviceworkerreloadpage', function(event) {
6 | // singlePageApp is just something I made up
7 | if (singlePageApp.interactedWith) {
8 | event.waitUntil(new Promise(function(resolve, reject) {
9 | var updateBanner = new singlePageApp.UpdateBanner();
10 | updateBanner.okButton.addEventListener('click', resolve);
11 | updateBanner.show();
12 | }));
13 | }
14 | });
15 | }
--------------------------------------------------------------------------------
/todo-app/example.com/ctrl.js:
--------------------------------------------------------------------------------
1 | this.version = 1.0;
2 | var cacheNames = {
3 | 'static': 'static' + this.version,
4 | 'core': 'core' + this.version
5 | };
6 |
7 | // Install process
8 | this.oninstalled = function(event) {
9 | caches.set(cacheNames['static'], new Cache(
10 | '//cdn.example.com/all-v1.css',
11 | '//cdn.example.com/all-v1.js',
12 | // TODO: how can we avoid downloading both PNGs?
13 | // https://github.com/slightlyoff/NavigationController/issues/60
14 | '//cdn.example.com/whatever-v1.png',
15 | '//cdn.example.com/whatever-large-v1.png',
16 | '//cdn.example.com/whatever-v1.woff'
17 | ));
18 |
19 | // core cache entried should be check on each controller update
20 | caches.set(cacheNames['core'], new Cache([
21 | '/'
22 | ]));
23 |
24 | event.waitUntil(Promise.all(
25 | caches.values().map(function(x) { return x.ready(); })
26 | )).then(function() {
27 | if (event.previousVersion) {
28 | event.reloadAll();
29 | }
30 | else {
31 | // if no previous version, we may as well take over now
32 | event.replace();
33 | }
34 | });
35 | };
36 |
37 | this.onactivate = function(event) {
38 | var expectedCaches = Object.keys(cacheNames).map(function(key) {
39 | return cacheNames[key];
40 | });
41 |
42 | // remove caches that shouldn't be there
43 | caches.keys.filter(function(cacheName) {
44 | return expectedCaches.indexOf(cacheName) == -1;
45 | }).forEach(caches.delete.bind(caches));
46 | };
47 |
48 |
49 | // Request handling
50 | this.addEventListener('fetch', function(event) {
51 | if (event.request.url.host == "cdn.example.com") {
52 | event.respondWith(caches.match(cacheNames['static'], event.request.url).catch(function() {
53 | return fetch(event.request);
54 | }));
55 | }
56 | else {
57 | event.respondWith(caches.match(cacheNames['core'], event.request.url).catch(function() {
58 | return fetch(event.request);
59 | }));
60 | }
61 | });
--------------------------------------------------------------------------------
/todo-app/example.com/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Single page app
5 |
6 |
7 |
8 |
9 |
Single page app
10 |
11 |
--------------------------------------------------------------------------------
/twitter-client/README.md:
--------------------------------------------------------------------------------
1 | Moved here: https://github.com/jakearchibald/tweetdeck-prototype
2 |
--------------------------------------------------------------------------------
/wiki/README.md:
--------------------------------------------------------------------------------
1 | ## Simple wiki
2 | This demo will show ServiceWorkers working in a wiki to give the user an offline experience. ServiceWorkers are being built to work for many use cases; and the wiki use case is one of the most simple and most popular. This demo should:
3 |
4 | * allow a user to 'save' articles to view them offline
5 | * when offline, the user should be able to navigate back to these articles and view them.
6 |
7 | For this demo you're going to need to [1] register a ServiceWorker [2] detect fetches and [3] use the ServiceWorker cache. For extra-bonus points the demo app could also:
8 |
9 | * allow the user to edit an article offline
10 | * allow the user to create an article while offline.
11 |
12 | ### More Information
13 | Please go ahead and create a demo app based on the info above! If you do want some more in-detail requirements, then please keep reading! More information / requirements:
14 |
15 | * User is viewing an article, and clicks “read later” on an article for the first time
16 | * Bootstrap code and related imagery requests added to a ServiceWorker cache, this process fails if any request fails
17 | * Articles in the cache should include the html & device-dependant inline images requests, and this process should fail if any request fails
18 | * User should see some confirmation when the article has been saved into the cache
19 | * Otherwise, a meaningful error message displayed (by the site, not browser UI)
20 | * User visits homepage
21 | * User should see a list of the articles they have saved in the cache
22 | * "remove" buttons for the articles the user has saved should be shown and be active
23 | * (for bonus points) A wiki often displays an "article of the day", so the main page should try to fetch this via XHR
24 | * If XHR fails, unobtrusive message indicating the user is offline is displayed in place of content
25 | * User visits cached article
26 | * The page structure is pulled from the ServiceWorker cache
27 | * Cached content is injected into the content area of the page
28 | * (for bonus points) Some articles may include additional "online-only content" fetched via XHR, eg login state
29 | * If offline, this should Fails silently, or displays small “offline mode” as login state
30 | * The cached article may have an html include, this is then requested when a user visits this page
31 | * If request succeeds (if a user is online), update content on page and replace cached content with new content
32 | * If fails, fail silently
33 | * User visits uncached article
34 | * The page should be requested from the server (normal request behaviour)
35 | * If fails due to network failure (no connection), friendly error message displayed, explaining the user is offline, listing article that are available offline
36 | * On navigate, if a check hasn’t been made for 10 minutes, look for updates to the bootstrap and page templates, update accordingly.
37 |
38 | ### Questions
39 | If you have questions please ask them in the issues. Just start a new issue with your question.
40 |
--------------------------------------------------------------------------------
/wiki/cdn.example.com/all-v1.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'whatever';
3 | src: url('whatever-v1.woff') format('woff');
4 | }
5 |
6 | html {
7 | background: url('whatever-v1.png');
8 | }
9 |
10 | /*
11 | Using device-width intentionally as we take the biggest required
12 | file offline
13 | */
14 | @media screen and (min-device-width: 500px) {
15 | html {
16 | background: url('whatever-large-v1.png');
17 | }
18 | }
--------------------------------------------------------------------------------
/wiki/cdn.example.com/all-v1.js:
--------------------------------------------------------------------------------
1 | // set up the controller
2 | if (navigator.registerController) {
3 | // TODO: this shouldn't happen until the user takes an article offline
4 | navigator.registerController("/*", "/ctrl.js");
5 | }
--------------------------------------------------------------------------------
/wiki/example.com/ctrl.js:
--------------------------------------------------------------------------------
1 | this.version = 1.0;
2 | var cacheNames = {
3 | 'static': 'static' + this.version,
4 | 'core': 'core' + this.version
5 | };
6 |
7 | // Install process
8 | this.oninstalled = function(event) {
9 | var staticCache = new Cache();
10 | var oldStaticCache;
11 | // TODO: how can we avoid downloading both PNGs?
12 | // https://github.com/slightlyoff/NavigationController/issues/60
13 | var staticUrls = [
14 | '//cdn.example.com/all-v1.css',
15 | '//cdn.example.com/all-v1.js',
16 | '//cdn.example.com/whatever-v1.png',
17 | '//cdn.example.com/whatever-large-v1.png',
18 | '//cdn.example.com/whatever-v1.woff'
19 | ];
20 |
21 | if (event.previousVersion) {
22 | oldStaticCache = caches.get('static' + event.previousVersion);
23 | }
24 |
25 | staticUrls.forEach(function(staticUrl) {
26 | // copy from previous cache, if it's there
27 | if (oldStaticCache && oldStaticCache.has(staticUrl)) {
28 | staticCache.set(staticUrl, oldStaticCache.get(staticUrl));
29 | }
30 | else {
31 | staticCache.add(staticUrl);
32 | }
33 | });
34 |
35 | caches.set(cacheNames['static'], staticCache);
36 |
37 | // core cache entried should be check on each controller update
38 | caches.set(cacheNames['core'], new Cache([
39 | '/index.html'
40 | ]));
41 |
42 | event.waitUntil(Promise.every(
43 | caches.values().map(function(x) { return x.ready(); })
44 | )).then(function() {
45 | // if no previous version, we may as well take over now
46 | if (!event.previousVersion) {
47 | event.replace();
48 | }
49 | });
50 | };
51 |
52 | this.onactivate = function(event) {
53 | var expectedCaches = Object.keys(cacheNames).map(function(key) {
54 | return cacheNames[key];
55 | });
56 |
57 | // remove caches that shouldn't be there
58 | caches.keys.filter(function(cacheName) {
59 | return expectedCaches.indexOf(cacheName) == -1;
60 | }).forEach(caches.delete.bind(caches));
61 | };
62 |
63 |
64 | // Request handling
65 | this.addEventListener('fetch', function(event) {
66 | if (event.request.url.host == "cdn.example.com") {
67 | event.respondWith(caches.match(cacheNames['static'], event.request.url).catch(function() {
68 | return fetch(event.request);
69 | }));
70 | }
71 | else {
72 | event.respondWith(caches.match(cacheNames['core'], event.request.url).catch(function() {
73 | return fetch(event.request);
74 | }));
75 | }
76 | });
--------------------------------------------------------------------------------
/wiki/example.com/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Wikipedia
5 |
6 |
7 |
8 |
9 |