UNPKG

9.97 kBJavaScriptView Raw
1/**
2 * Copyright 2016 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15*/
16
17// DO NOT EDIT THIS GENERATED OUTPUT DIRECTLY!
18// This file should be overwritten as part of your build process.
19// If you need to extend the behavior of the generated service worker, the best approach is to write
20// additional code and include it using the importScripts option:
21// https://github.com/GoogleChrome/sw-precache#importscripts-arraystring
22//
23// Alternatively, it's possible to make changes to the underlying template file and then use that as the
24// new base for generating output, via the templateFilePath option:
25// https://github.com/GoogleChrome/sw-precache#templatefilepath-string
26//
27// If you go that route, make sure that whenever you update your sw-precache dependency, you reconcile any
28// changes made to this original template file with your modified copy.
29
30// This generated service worker JavaScript will precache your site's resources.
31// The code needs to be saved in a .js file at the top-level of your site, and registered
32// from your pages in order to be used. See
33// https://github.com/googlechrome/sw-precache/blob/master/demo/app/js/service-worker-registration.js
34// for an example of how you can register this script and handle various service worker events.
35
36/* eslint-env worker, serviceworker */
37/* eslint-disable indent, no-unused-vars, no-multiple-empty-lines, max-nested-callbacks, space-before-function-paren, quotes, comma-spacing */
38'use strict';
39
40var precacheConfig = [["/mirage/index.js","4f6d556e043f9b14847fda071664d591"]];
41var cacheName = 'sw-precache-v3-sw-precache-webpack-plugin-' + (self.registration ? self.registration.scope : '');
42
43
44var ignoreUrlParametersMatching = [/^utm_/];
45
46
47
48var addDirectoryIndex = function(originalUrl, index) {
49 var url = new URL(originalUrl);
50 if (url.pathname.slice(-1) === '/') {
51 url.pathname += index;
52 }
53 return url.toString();
54 };
55
56var cleanResponse = function(originalResponse) {
57 // If this is not a redirected response, then we don't have to do anything.
58 if (!originalResponse.redirected) {
59 return Promise.resolve(originalResponse);
60 }
61
62 // Firefox 50 and below doesn't support the Response.body stream, so we may
63 // need to read the entire body to memory as a Blob.
64 var bodyPromise = 'body' in originalResponse ?
65 Promise.resolve(originalResponse.body) :
66 originalResponse.blob();
67
68 return bodyPromise.then(function(body) {
69 // new Response() is happy when passed either a stream or a Blob.
70 return new Response(body, {
71 headers: originalResponse.headers,
72 status: originalResponse.status,
73 statusText: originalResponse.statusText
74 });
75 });
76 };
77
78var createCacheKey = function(originalUrl, paramName, paramValue,
79 dontCacheBustUrlsMatching) {
80 // Create a new URL object to avoid modifying originalUrl.
81 var url = new URL(originalUrl);
82
83 // If dontCacheBustUrlsMatching is not set, or if we don't have a match,
84 // then add in the extra cache-busting URL parameter.
85 if (!dontCacheBustUrlsMatching ||
86 !(url.pathname.match(dontCacheBustUrlsMatching))) {
87 url.search += (url.search ? '&' : '') +
88 encodeURIComponent(paramName) + '=' + encodeURIComponent(paramValue);
89 }
90
91 return url.toString();
92 };
93
94var isPathWhitelisted = function(whitelist, absoluteUrlString) {
95 // If the whitelist is empty, then consider all URLs to be whitelisted.
96 if (whitelist.length === 0) {
97 return true;
98 }
99
100 // Otherwise compare each path regex to the path of the URL passed in.
101 var path = (new URL(absoluteUrlString)).pathname;
102 return whitelist.some(function(whitelistedPathRegex) {
103 return path.match(whitelistedPathRegex);
104 });
105 };
106
107var stripIgnoredUrlParameters = function(originalUrl,
108 ignoreUrlParametersMatching) {
109 var url = new URL(originalUrl);
110 // Remove the hash; see https://github.com/GoogleChrome/sw-precache/issues/290
111 url.hash = '';
112
113 url.search = url.search.slice(1) // Exclude initial '?'
114 .split('&') // Split into an array of 'key=value' strings
115 .map(function(kv) {
116 return kv.split('='); // Split each 'key=value' string into a [key, value] array
117 })
118 .filter(function(kv) {
119 return ignoreUrlParametersMatching.every(function(ignoredRegex) {
120 return !ignoredRegex.test(kv[0]); // Return true iff the key doesn't match any of the regexes.
121 });
122 })
123 .map(function(kv) {
124 return kv.join('='); // Join each [key, value] array into a 'key=value' string
125 })
126 .join('&'); // Join the array of 'key=value' strings into a string with '&' in between each
127
128 return url.toString();
129 };
130
131
132var hashParamName = '_sw-precache';
133var urlsToCacheKeys = new Map(
134 precacheConfig.map(function(item) {
135 var relativeUrl = item[0];
136 var hash = item[1];
137 var absoluteUrl = new URL(relativeUrl, self.location);
138 var cacheKey = createCacheKey(absoluteUrl, hashParamName, hash, /\.\w{8}\./);
139 return [absoluteUrl.toString(), cacheKey];
140 })
141);
142
143function setOfCachedUrls(cache) {
144 return cache.keys().then(function(requests) {
145 return requests.map(function(request) {
146 return request.url;
147 });
148 }).then(function(urls) {
149 return new Set(urls);
150 });
151}
152
153self.addEventListener('install', function(event) {
154 event.waitUntil(
155 caches.open(cacheName).then(function(cache) {
156 return setOfCachedUrls(cache).then(function(cachedUrls) {
157 return Promise.all(
158 Array.from(urlsToCacheKeys.values()).map(function(cacheKey) {
159 // If we don't have a key matching url in the cache already, add it.
160 if (!cachedUrls.has(cacheKey)) {
161 var request = new Request(cacheKey, {credentials: 'same-origin'});
162 return fetch(request).then(function(response) {
163 // Bail out of installation unless we get back a 200 OK for
164 // every request.
165 if (!response.ok) {
166 throw new Error('Request for ' + cacheKey + ' returned a ' +
167 'response with status ' + response.status);
168 }
169
170 return cleanResponse(response).then(function(responseToCache) {
171 return cache.put(cacheKey, responseToCache);
172 });
173 });
174 }
175 })
176 );
177 });
178 }).then(function() {
179
180 // Force the SW to transition from installing -> active state
181 return self.skipWaiting();
182
183 })
184 );
185});
186
187self.addEventListener('activate', function(event) {
188 var setOfExpectedUrls = new Set(urlsToCacheKeys.values());
189
190 event.waitUntil(
191 caches.open(cacheName).then(function(cache) {
192 return cache.keys().then(function(existingRequests) {
193 return Promise.all(
194 existingRequests.map(function(existingRequest) {
195 if (!setOfExpectedUrls.has(existingRequest.url)) {
196 return cache.delete(existingRequest);
197 }
198 })
199 );
200 });
201 }).then(function() {
202
203 return self.clients.claim();
204
205 })
206 );
207});
208
209
210self.addEventListener('fetch', function(event) {
211 if (event.request.method === 'GET') {
212 // Should we call event.respondWith() inside this fetch event handler?
213 // This needs to be determined synchronously, which will give other fetch
214 // handlers a chance to handle the request if need be.
215 var shouldRespond;
216
217 // First, remove all the ignored parameters and hash fragment, and see if we
218 // have that URL in our cache. If so, great! shouldRespond will be true.
219 var url = stripIgnoredUrlParameters(event.request.url, ignoreUrlParametersMatching);
220 shouldRespond = urlsToCacheKeys.has(url);
221
222 // If shouldRespond is false, check again, this time with 'index.html'
223 // (or whatever the directoryIndex option is set to) at the end.
224 var directoryIndex = 'index.html';
225 if (!shouldRespond && directoryIndex) {
226 url = addDirectoryIndex(url, directoryIndex);
227 shouldRespond = urlsToCacheKeys.has(url);
228 }
229
230 // If shouldRespond is still false, check to see if this is a navigation
231 // request, and if so, whether the URL matches navigateFallbackWhitelist.
232 var navigateFallback = '/mirage/index.html';
233 if (!shouldRespond &&
234 navigateFallback &&
235 (event.request.mode === 'navigate') &&
236 isPathWhitelisted(["^(?!\\/__).*"], event.request.url)) {
237 url = new URL(navigateFallback, self.location).toString();
238 shouldRespond = urlsToCacheKeys.has(url);
239 }
240
241 // If shouldRespond was set to true at any point, then call
242 // event.respondWith(), using the appropriate cache key.
243 if (shouldRespond) {
244 event.respondWith(
245 caches.open(cacheName).then(function(cache) {
246 return cache.match(urlsToCacheKeys.get(url)).then(function(response) {
247 if (response) {
248 return response;
249 }
250 throw Error('The cached response that was expected is missing.');
251 });
252 }).catch(function(e) {
253 // Fall back to just fetch()ing the request if some unexpected error
254 // prevented the cached response from being valid.
255 console.warn('Couldn\'t serve response for "%s" from cache: %O', event.request.url, e);
256 return fetch(event.request);
257 })
258 );
259 }
260 }
261});
262
263
264
265
266
267
268