-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathsw.js
124 lines (108 loc) · 4.43 KB
/
sw.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* eslint-env serviceworker, browser */
// sw-offline-google-analytics *must* be imported and initialized before
// sw-toolbox, because its 'fetch' event handler needs to run first.
importScripts('/sw-offline-google-analytics/offline-google-analytics-import.js');
goog.offlineGoogleAnalytics.initialize();
// Use sw-toolbox
importScripts('/sw-toolbox/sw-toolbox.js'); /* global toolbox */
toolbox.options.debug = false;
// Use page transitions
importScripts('/js/sw-page-transition.js'); /* global transition */
const VERSION = '2';
const PREFIX = 'gulliver';
const CACHE_NAME = `${PREFIX}-v${VERSION}`;
// URL to return in place of the "offline dino" when client is
// offline and requests a URL that's not in the cache.
const OFFLINE_URL = '/.shell/offline';
// Page transitions
const TRANSITION_PWA_LIST = '/transitions/pwas';
const TRANSITION_PWA_VIEW = '/transitions/pwas/view';
const OFFLINE = [
OFFLINE_URL,
'/img/GitHub-Mark-Light-24px.png',
'/img/GitHub-Mark-Light-48px.png',
'/img/lighthouse.svg',
'/css/style.css',
'/sw.js',
'/js/gulliver.js',
'/messaging-config.json',
'/js/pwas-list-transition.js',
'/js/pwas-view-transition.js',
TRANSITION_PWA_LIST,
TRANSITION_PWA_VIEW
];
toolbox.precache(OFFLINE);
toolbox.options.cache.name = CACHE_NAME;
// Cache the page registering the service worker. Without this, the
// "first" page the user visits is only cached on the second visit,
// since the first load is uncontrolled.
toolbox.precache(
clients.matchAll({includeUncontrolled: true}).then(l => {
return l.map(c => c.url);
})
);
// Register and cache page transitions for list and detail page
transition.cacheName(toolbox.options.cache.name)
.registerPageTransition(/\/pwas\/.*/, TRANSITION_PWA_VIEW)
.registerPageTransition(/\/.*/, TRANSITION_PWA_LIST);
// Provide an API for the front end to determine which resources are available in the
// cache. We could have also established a new endpoint, or implemented support
// for 'only-if-cached', but the HEAD method was unused.
toolbox.router.head(/^/, request => {
// Simulate RFC7234's only-if-cached mechanism so that the front end is able to
// determine which links work offline. Also very similar to sw-toolbox's cacheOnly
// strategy, except that we cache.match(url) rather than cache.match(request) so
// that the HEAD method is ignored on cache.match().
function onlyIfCached(url) {
return caches.open(CACHE_NAME).then(cache => {
return cache.match(url).then(response => {
return (response && response.status === 200) ? response : new Response('', {
status: 504,
statusText: 'Gateway Timeout'
});
});
});
}
return onlyIfCached(request.url);
});
toolbox.router.get('/', (request, values, options) => {
// Replace requests to start_url with the lastest version of the root page.
// TODO Make more generic: strip utm_* parameters from *every* request.
// TODO Pass through credentials (e.g. cookies) and other request metadata, see
// https://github.com/ithinkihaveacat/sw-proxy/blob/master/http-proxy.ts#L249.
if (request.url.endsWith('/?utm_source=homescreen')) {
request = new Request('/');
}
return toolbox.router.default(request, values, options);
});
toolbox.router.default = (request, values, options) => {
return transition.fetchWithPageTransition(request).then(response => {
// Return page transition or network first if not available
return response || toolbox
.networkFirst(request, values, options)
.catch(_ => {
// networkFirst failed (no network and not in cache)
return caches.open(toolbox.options.cache.name).then(cache => {
return cache.match(OFFLINE_URL).then(response => {
return response || new Response('', {
status: 500,
statusText: 'Offline Page Missing'
});
});
});
});
});
};
self.addEventListener('activate', () => self.clients.claim());
// Delete old caches and claim clients so that the very first page load is controlled by a service
// worker. (Important for responding correctly in offline state.)
self.addEventListener('activate', () =>
caches.keys().then(cacheNames =>
Promise.all(
cacheNames.filter(cacheName => cacheName !== CACHE_NAME)
.map(cacheName => caches.delete(cacheName))
).then(self.clients.claim())
)
);
// Make sure the SW the page we register() is the service we use.
self.addEventListener('install', () => self.skipWaiting());