diff options
| author | BrokenTalentsFun CI <ci@brokentalents.fun> | 2018-06-08 19:36:11 +0200 |
|---|---|---|
| committer | schneefux <schneefux+commit@schneefux.xyz> | 2018-12-13 17:09:16 +0100 |
| commit | 10cf870629e860616899848d7f1c849d0b810342 (patch) | |
| tree | 4c7e2831f3857c07681fefee1611d1c49f0ef25b /dist/workbox-v3.2.0/workbox-precaching.dev.js | |
| parent | 505a67dc32206a0c603258d856fcbe00e53fc1f5 (diff) | |
| download | brokentalents-10cf870629e860616899848d7f1c849d0b810342.tar.gz brokentalents-10cf870629e860616899848d7f1c849d0b810342.zip | |
automatic build
Diffstat (limited to 'dist/workbox-v3.2.0/workbox-precaching.dev.js')
| -rw-r--r-- | dist/workbox-v3.2.0/workbox-precaching.dev.js | 1154 |
1 files changed, 1154 insertions, 0 deletions
diff --git a/dist/workbox-v3.2.0/workbox-precaching.dev.js b/dist/workbox-v3.2.0/workbox-precaching.dev.js new file mode 100644 index 0000000..c7f6ec2 --- /dev/null +++ b/dist/workbox-v3.2.0/workbox-precaching.dev.js @@ -0,0 +1,1154 @@ +this.workbox = this.workbox || {}; +this.workbox.precaching = (function (DBWrapper_mjs,logger_mjs,cacheNames_mjs,WorkboxError_mjs,fetchWrapper_mjs,cacheWrapper_mjs,assert_mjs,getFriendlyURL_mjs) { +'use strict'; + +try { + self.workbox.v['workbox:precaching:3.2.0'] = 1; +} catch (e) {} // eslint-disable-line + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * Used as a consistent way of referencing a URL to precache. + * + * @private + * @memberof module:workbox-precaching + */ +class PrecacheEntry { + /** + * This class ensures all cache list entries are consistent and + * adds cache busting if required. + * + * @param {*} originalInput + * @param {string} url + * @param {string} revision + * @param {boolean} shouldCacheBust + */ + constructor(originalInput, url, revision, shouldCacheBust) { + this._originalInput = originalInput; + this._entryId = url; + this._revision = revision; + const requestAsCacheKey = new Request(url, { credentials: 'same-origin' }); + this._cacheRequest = requestAsCacheKey; + this._networkRequest = shouldCacheBust ? this._cacheBustRequest(requestAsCacheKey) : requestAsCacheKey; + } + + /** + * This method will either use Request.cache option OR append a cache + * busting parameter to the URL. + * + * @param {Request} request The request to cache bust + * @return {Request} A cachebusted Request + * + * @private + */ + _cacheBustRequest(request) { + let url = request.url; + const requestOptions = { + credentials: 'same-origin' + }; + if ('cache' in Request.prototype) { + // Make use of the Request cache mode where we can. + // Reload skips the HTTP cache for outgoing requests and updates + // the cache with the returned response. + requestOptions.cache = 'reload'; + } else { + const parsedURL = new URL(url, location); + + // This is done so the minifier can mangle 'global.encodeURIComponent' + const _encodeURIComponent = encodeURIComponent; + + parsedURL.search += (parsedURL.search ? '&' : '') + _encodeURIComponent(`_workbox-cache-bust`) + '=' + _encodeURIComponent(this._revision); + url = parsedURL.toString(); + } + + return new Request(url, requestOptions); + } +} + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Allows minifier to mangle this name +const REVISON_IDB_FIELD = 'revision'; +const URL_IDB_FIELD = 'url'; +const DB_STORE_NAME = 'precached-details-models'; +/** + * This model will track the relevant information of entries that + * are cached and their matching revision details. + * + * @private + */ +class PrecachedDetailsModel { + /** + * Construct a new model for a specific cache. + * + * @param {string} dbName + * @private + */ + constructor(dbName) { + // This ensures the db name contains only letters, numbers, '-', '_' and '$' + const filteredDBName = dbName.replace(/[^\w-]/g, '_'); + this._db = new DBWrapper_mjs.DBWrapper(filteredDBName, 2, { + onupgradeneeded: this._handleUpgrade + }); + } + + /** + * Should perform an upgrade of indexedDB. + * + * @param {Event} evt + * + * @private + */ + _handleUpgrade(evt) { + const db = evt.target.result; + if (evt.oldVersion < 2) { + // IndexedDB version 1 used both 'workbox-precaching' and + // 'precached-details-model' before upgrading to version 2. + // Delete them and create a new store with latest schema. + if (db.objectStoreNames.contains('workbox-precaching')) { + db.deleteObjectStore('workbox-precaching'); + } + if (db.objectStoreNames.contains(DB_STORE_NAME)) { + db.deleteObjectStore(DB_STORE_NAME); + } + } + db.createObjectStore(DB_STORE_NAME); + } + + /** + * Check if an entry is already cached. Returns false if + * the entry isn't cached or the revision has changed. + * + * @param {string} cacheName + * @param {PrecacheEntry} precacheEntry + * @return {boolean} + * + * @private + */ + _isEntryCached(cacheName, precacheEntry) { + var _this = this; + + return babelHelpers.asyncToGenerator(function* () { + const revisionDetails = yield _this._getRevision(precacheEntry._entryId); + if (revisionDetails !== precacheEntry._revision) { + return false; + } + + const openCache = yield caches.open(cacheName); + const cachedResponse = yield openCache.match(precacheEntry._cacheRequest); + return !!cachedResponse; + })(); + } + + /** + * @return {Promise<Array>} + * + * @private + */ + _getAllEntries() { + var _this2 = this; + + return babelHelpers.asyncToGenerator(function* () { + return yield _this2._db.getAllMatching(DB_STORE_NAME, { + includeKeys: true + }); + })(); + } + + /** + * Get the current revision details. + * + * @param {Object} entryId + * @return {Promise<string|null>} + * + * @private + */ + _getRevision(entryId) { + var _this3 = this; + + return babelHelpers.asyncToGenerator(function* () { + const data = yield _this3._db.get(DB_STORE_NAME, entryId); + return data ? data[REVISON_IDB_FIELD] : null; + })(); + } + + /** + * Add an entry to the details model. + * + * @param {PrecacheEntry} precacheEntry + * + * @private + */ + _addEntry(precacheEntry) { + var _this4 = this; + + return babelHelpers.asyncToGenerator(function* () { + yield _this4._db.put(DB_STORE_NAME, { + [REVISON_IDB_FIELD]: precacheEntry._revision, + [URL_IDB_FIELD]: precacheEntry._cacheRequest.url + }, precacheEntry._entryId); + })(); + } + + /** + * Delete entry from details model. + * + * @param {string} entryId + * + * @private + */ + _deleteEntry(entryId) { + var _this5 = this; + + return babelHelpers.asyncToGenerator(function* () { + yield _this5._db.delete(DB_STORE_NAME, entryId); + })(); + } +} + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * This method will print out a warning if a precache entry doesn't have + * a `revision` value. + * + * This is common if the asset if revisioned in the url like `index.1234.css`. + * + * @param {Map} entriesMap + * + * @private + * @memberof module:workbox-preaching + */ +var showWarningsIfNeeded = (entriesMap => { + const urlOnlyEntries = []; + entriesMap.forEach(entry => { + if (typeof entry === 'string' || !entry._originalInput.revision) { + urlOnlyEntries.push(entry._originalInput); + } + }); + + if (urlOnlyEntries.length === 0) { + // No warnings needed. + return; + } + + logger_mjs.logger.groupCollapsed('Are your precached assets revisioned?'); + + const urlsList = urlOnlyEntries.map(urlOnlyEntry => { + return ` - ${JSON.stringify(urlOnlyEntry)}`; + }).join(`\n`); + + logger_mjs.logger.warn(`The following precache entries might not be revisioned:` + `\n\n` + urlsList + `\n\n`); + + logger_mjs.logger.unprefixed.warn(`You can learn more about why this might be a ` + `problem here: https://developers.google.com/web/tools/workbox/modules/workbox-precaching`); + + logger_mjs.logger.groupEnd(); +}); + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @param {string} groupTitle + * @param {Array<PrecacheEntry>} entries + * + * @private + */ +const _nestedGroup = (groupTitle, entries) => { + if (entries.length === 0) { + return; + } + + logger_mjs.logger.groupCollapsed(groupTitle); + + entries.forEach(entry => { + logger_mjs.logger.log(entry._originalInput); + }); + + logger_mjs.logger.groupEnd(); +}; + +/** + * @param {Array<Object>} entriesToPrecache + * @param {Array<Object>} alreadyPrecachedEntries + * + * @private + * @memberof module:workbox-precachig + */ +var printInstallDetails = ((entriesToPrecache, alreadyPrecachedEntries) => { + // Goal is to print the message: + // Precaching X files. + // Or: + // Precaching X files. Y files were cached and up-to-date. + + const precachedCount = entriesToPrecache.length; + const alreadyPrecachedCount = alreadyPrecachedEntries.length; + let printText = `Precaching ${precachedCount} file${precachedCount === 1 ? '' : 's'}.`; + if (alreadyPrecachedCount > 0) { + printText += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? ' is' : 's are'} already cached.`; + } + + logger_mjs.logger.groupCollapsed(printText); + + _nestedGroup(`View precached URLs.`, entriesToPrecache); + _nestedGroup(`View URLs that were already precached.`, alreadyPrecachedEntries); + logger_mjs.logger.groupEnd(); +}); + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +const logGroup = (groupTitle, urls) => { + logger_mjs.logger.groupCollapsed(groupTitle); + + urls.forEach(url => { + logger_mjs.logger.log(url); + }); + + logger_mjs.logger.groupEnd(); +}; + +/** + * @param {Array<string>} deletedCacheRequests + * @param {Array<string>} deletedRevisionDetails + * + * @private + * @memberof module:workbox-precachig + */ +var printCleanupDetails = ((deletedCacheRequests, deletedRevisionDetails) => { + if (deletedCacheRequests.length === 0 && deletedRevisionDetails.length === 0) { + return; + } + + const cacheDeleteCount = deletedCacheRequests.length; + const revisionDeleteCount = deletedRevisionDetails.length; + + const cacheDeleteText = `${cacheDeleteCount} cached ` + `request${cacheDeleteCount === 1 ? ' was' : 's were'} deleted`; + const revisionDeleteText = `${revisionDeleteCount} ` + `${revisionDeleteCount === 1 ? 'entry' : 'entries'} ` + `${revisionDeleteCount === 1 ? 'was' : 'were'} deleted from IndexedDB.`; + + logger_mjs.logger.groupCollapsed(`During precaching cleanup, ${cacheDeleteText} and ${revisionDeleteText}`); + + logGroup('Deleted Cache Requests', deletedCacheRequests); + logGroup('Revision Details Deleted from DB', deletedRevisionDetails); + + logger_mjs.logger.groupEnd(); +}); + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @param {Response} response + * @return {Response} + * + * @private + * @memberof module:workbox-precachig + */ +const cleanRedirect = (() => { + var _ref = babelHelpers.asyncToGenerator(function* (response) { + const clonedResponse = response.clone(); + + // Not all browsers support the Response.body stream, so fall back + // to reading the entire body into memory as a blob. + const bodyPromise = 'body' in clonedResponse ? Promise.resolve(clonedResponse.body) : clonedResponse.blob(); + + const body = yield bodyPromise; + + // new Response() is happy when passed either a stream or a Blob. + return new Response(body, ['headers', 'status', 'statusText'].map(function (key) { + return clonedResponse[key]; + })); + }); + + return function cleanRedirect(_x) { + return _ref.apply(this, arguments); + }; +})(); + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * Performs efficient precaching of assets. + * + * @memberof workbox.precaching + */ +class PrecacheController { + /** + * Create a new PrecacheController. + * + * @param {string} cacheName + */ + constructor(cacheName) { + this._cacheName = cacheNames_mjs.cacheNames.getPrecacheName(cacheName); + this._entriesToCacheMap = new Map(); + this._precacheDetailsModel = new PrecachedDetailsModel(this._cacheName); + } + + /** + * This method will add items to the precache list, removing duplicates + * and ensuring the information is valid. + * + * @param { + * Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string> + * } entries Array of entries to + * precache. + */ + addToCacheList(entries) { + { + assert_mjs.assert.isArray(entries, { + moduleName: 'workbox-precaching', + className: 'PrecacheController', + funcName: 'addToCacheList', + paramName: 'entries' + }); + } + + entries.map(userEntry => { + this._addEntryToCacheList(this._parseEntry(userEntry)); + }); + } + + /** + * This method returns a precache entry. + * + * @private + * @param {string|Object} input + * @return {PrecacheEntry} + */ + _parseEntry(input) { + switch (typeof input) { + case 'string': + { + { + if (input.length === 0) { + throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-unexpected-type', { + entry: input + }); + } + } + + return new PrecacheEntry(input, input, input); + } + case 'object': + { + { + if (!input || !input.url) { + throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-unexpected-type', { + entry: input + }); + } + } + + return new PrecacheEntry(input, input.url, input.revision || input.url, !!input.revision); + } + default: + throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-unexpected-type', { + entry: input + }); + } + } + + /** + * Adds an entry to the precache list, accounting for possible duplicates. + * + * @private + * @param {PrecacheEntry} entryToAdd + */ + _addEntryToCacheList(entryToAdd) { + // Check if the entry is already part of the map + const existingEntry = this._entriesToCacheMap.get(entryToAdd._entryId); + if (!existingEntry) { + this._entriesToCacheMap.set(entryToAdd._entryId, entryToAdd); + return; + } + + // Duplicates are fine, but make sure the revision information + // is the same. + if (existingEntry._revision !== entryToAdd._revision) { + throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-conflicting-entries', { + firstEntry: existingEntry._originalInput, + secondEntry: entryToAdd._originalInput + }); + } + } + + /** + * Call this method from a service work install event to start + * precaching assets. + * + * @param {Object} options + * @param {boolean} options.suppressWarnings Suppress warning messages. + * @param {Array<Object>} options.plugins Plugins to be used for fetching + * and caching during install. + * @return { + * Promise<workbox.precaching.InstallResult>} + */ + install(options = {}) { + var _this = this; + + return babelHelpers.asyncToGenerator(function* () { + { + if (options.suppressWarnings !== true) { + showWarningsIfNeeded(_this._entriesToCacheMap); + } + + if (options.plugins) { + assert_mjs.assert.isArray(options.plugins, { + moduleName: 'workbox-precaching', + className: 'PrecacheController', + funcName: 'install', + paramName: 'plugins' + }); + } + } + + // Empty the temporary cache. + // NOTE: We remove all entries instead of deleting the cache as the cache + // may be marked for deletion but still exist until a later stage + // resulting in unexpected behavior of being deletect when all references + // are dropped. + // https://github.com/GoogleChrome/workbox/issues/1368 + const tempCache = yield caches.open(_this._getTempCacheName()); + const requests = yield tempCache.keys(); + yield Promise.all(requests.map(function (request) { + return tempCache.delete(request); + })); + + const entriesToPrecache = []; + const entriesAlreadyPrecached = []; + + for (const precacheEntry of _this._entriesToCacheMap.values()) { + if (yield _this._precacheDetailsModel._isEntryCached(_this._cacheName, precacheEntry)) { + entriesAlreadyPrecached.push(precacheEntry); + } else { + entriesToPrecache.push(precacheEntry); + } + } + + // Wait for all requests to be cached. + yield Promise.all(entriesToPrecache.map(function (precacheEntry) { + return _this._cacheEntryInTemp(precacheEntry, options.plugins); + })); + + { + printInstallDetails(entriesToPrecache, entriesAlreadyPrecached); + } + + return { + updatedEntries: entriesToPrecache, + notUpdatedEntries: entriesAlreadyPrecached + }; + })(); + } + + /** + * Takes the current set of temporary files and moves them to the final + * cache, deleting the temporary cache once copying is complete. + * + * @param {Object} options + * @param {Array<Object>} options.plugins Plugins to be used for fetching + * and caching during install. + * @return { + * Promise<workbox.precaching.CleanupResult>} + * Resolves with an object containing details of the deleted cache requests + * and precache revision details. + */ + activate(options = {}) { + var _this2 = this; + + return babelHelpers.asyncToGenerator(function* () { + const tempCache = yield caches.open(_this2._getTempCacheName()); + + const requests = yield tempCache.keys(); + yield Promise.all(requests.map((() => { + var _ref = babelHelpers.asyncToGenerator(function* (request) { + const response = yield tempCache.match(request); + yield cacheWrapper_mjs.cacheWrapper.put(_this2._cacheName, request, response, options.plugins); + yield tempCache.delete(request); + }); + + return function (_x) { + return _ref.apply(this, arguments); + }; + })())); + + return _this2._cleanup(); + })(); + } + + /** + * Returns the name of the temporary cache. + * + * @return {string} + * + * @private + */ + _getTempCacheName() { + return `${this._cacheName}-temp`; + } + + /** + * Requests the entry and saves it to the cache if the response + * is valid. + * + * @private + * @param {BaseCacheEntry} precacheEntry The entry to fetch and cache. + * @param {Array<Object>} plugins Array of plugins to apply to fetch and + * caching. + * @return {Promise<boolean>} Returns a promise that resolves once the entry + * has been fetched and cached or skipped if no update is needed. The + * promise resolves with true if the entry was cached / updated and + * false if the entry is already cached and up-to-date. + */ + _cacheEntryInTemp(precacheEntry, plugins) { + var _this3 = this; + + return babelHelpers.asyncToGenerator(function* () { + let response = yield fetchWrapper_mjs.fetchWrapper.fetch(precacheEntry._networkRequest, null, plugins); + + if (response.redirected) { + response = yield cleanRedirect(response); + } + + yield cacheWrapper_mjs.cacheWrapper.put(_this3._getTempCacheName(), precacheEntry._cacheRequest, response, plugins); + + yield _this3._precacheDetailsModel._addEntry(precacheEntry); + + return true; + })(); + } + + /** + * Compare the URLs and determines which assets are no longer required + * in the cache. + * + * This should be called in the service worker activate event. + * + * @return { + * Promise<workbox.precaching.CleanupResult>} + * Resolves with an object containing details of the deleted cache requests + * and precache revision details. + * + * @private + */ + _cleanup() { + var _this4 = this; + + return babelHelpers.asyncToGenerator(function* () { + const expectedCacheUrls = []; + _this4._entriesToCacheMap.forEach(function (entry) { + const fullUrl = new URL(entry._cacheRequest.url, location).toString(); + expectedCacheUrls.push(fullUrl); + }); + + const [deletedCacheRequests, deletedRevisionDetails] = yield Promise.all([_this4._cleanupCache(expectedCacheUrls), _this4._cleanupDetailsModel(expectedCacheUrls)]); + + { + printCleanupDetails(deletedCacheRequests, deletedRevisionDetails); + } + + return { + deletedCacheRequests, + deletedRevisionDetails + }; + })(); + } + + /** + * Goes through all the cache entries and removes any that are + * outdated. + * + * @private + * @param {Array<string>} expectedCacheUrls Array of URLs that are + * expected to be cached. + * @return {Promise<Array<string>>} Resolves to an array of URLs + * of cached requests that were deleted. + */ + _cleanupCache(expectedCacheUrls) { + var _this5 = this; + + return babelHelpers.asyncToGenerator(function* () { + if (!(yield caches.has(_this5._cacheName))) { + // Cache doesn't exist, so nothing to delete + return []; + } + + const cache = yield caches.open(_this5._cacheName); + const cachedRequests = yield cache.keys(); + const cachedRequestsToDelete = cachedRequests.filter(function (cachedRequest) { + return !expectedCacheUrls.includes(new URL(cachedRequest.url, location).toString()); + }); + + yield Promise.all(cachedRequestsToDelete.map(function (cacheUrl) { + return cache.delete(cacheUrl); + })); + + return cachedRequestsToDelete.map(function (request) { + return request.url; + }); + })(); + } + + /** + * Goes through all entries in indexedDB and removes any that are outdated. + * + * @private + * @param {Array<string>} expectedCacheUrls Array of URLs that are + * expected to be cached. + * @return {Promise<Array<string>>} Resolves to an array of URLs removed + * from indexedDB. + */ + _cleanupDetailsModel(expectedCacheUrls) { + var _this6 = this; + + return babelHelpers.asyncToGenerator(function* () { + const revisionedEntries = yield _this6._precacheDetailsModel._getAllEntries(); + const detailsToDelete = revisionedEntries.filter(function (entry) { + const fullUrl = new URL(entry.value.url, location).toString(); + return !expectedCacheUrls.includes(fullUrl); + }); + + yield Promise.all(detailsToDelete.map(function (entry) { + return _this6._precacheDetailsModel._deleteEntry(entry.primaryKey); + })); + return detailsToDelete.map(function (entry) { + return entry.value.url; + }); + })(); + } + + /** + * Returns an array of fully qualified URL's that will be precached. + * + * @return {Array<string>} An array of URLs. + */ + getCachedUrls() { + return Array.from(this._entriesToCacheMap.keys()).map(url => new URL(url, location).href); + } +} + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + +var publicAPI = Object.freeze({ + PrecacheController: PrecacheController +}); + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +{ + assert_mjs.assert.isSwEnv('workbox-precaching'); +} + +let installActivateListenersAdded = false; +let fetchListenersAdded = false; +let suppressWarnings = false; +let plugins = []; + +const cacheName = cacheNames_mjs.cacheNames.getPrecacheName(); +const precacheController = new PrecacheController(cacheName); + +const _removeIgnoreUrlParams = (origUrlObject, ignoreUrlParametersMatching) => { + // Exclude initial '?' + const searchString = origUrlObject.search.slice(1); + + // Split into an array of 'key=value' strings + const keyValueStrings = searchString.split('&'); + const keyValuePairs = keyValueStrings.map(keyValueString => { + // Split each 'key=value' string into a [key, value] array + return keyValueString.split('='); + }); + const filteredKeyValuesPairs = keyValuePairs.filter(keyValuePair => { + return ignoreUrlParametersMatching.every(ignoredRegex => { + // Return true iff the key doesn't match any of the regexes. + return !ignoredRegex.test(keyValuePair[0]); + }); + }); + const filteredStrings = filteredKeyValuesPairs.map(keyValuePair => { + // Join each [key, value] array into a 'key=value' string + return keyValuePair.join('='); + }); + + // Join the array of 'key=value' strings into a string with '&' in + // between each + const urlClone = new URL(origUrlObject); + urlClone.search = filteredStrings.join('&'); + return urlClone; +}; + +/** + * This function will take the request URL and manipulate it based on the + * configuration options. + * + * @param {string} url + * @param {Object} options + * @return {string|null} Returns the URL in the cache that matches the request + * if available, other null. + * + * @private + */ +const _getPrecachedUrl = (url, { + ignoreUrlParametersMatching = [/^utm_/], + directoryIndex = 'index.html', + cleanUrls = true, + urlManipulation = null +} = {}) => { + const urlObject = new URL(url, location); + + // Change '/some-url#123' => '/some-url' + urlObject.hash = ''; + + const urlWithoutIgnoredParams = _removeIgnoreUrlParams(urlObject, ignoreUrlParametersMatching); + + let urlsToAttempt = [ + // Test the URL that was fetched + urlObject, + // Test the URL without search params + urlWithoutIgnoredParams]; + + // Test the URL with a directory index + if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) { + const directoryUrl = new URL(urlWithoutIgnoredParams); + directoryUrl.pathname += directoryIndex; + urlsToAttempt.push(directoryUrl); + } + + // Test the URL with a '.html' extension + if (cleanUrls) { + const cleanUrl = new URL(urlWithoutIgnoredParams); + cleanUrl.pathname += '.html'; + urlsToAttempt.push(cleanUrl); + } + + if (urlManipulation) { + const additionalUrls = urlManipulation({ url: urlObject }); + urlsToAttempt = urlsToAttempt.concat(additionalUrls); + } + + const cachedUrls = precacheController.getCachedUrls(); + for (const possibleUrl of urlsToAttempt) { + if (cachedUrls.indexOf(possibleUrl.href) !== -1) { + // It's a perfect match + { + logger_mjs.logger.debug(`Precaching found a match for ` + getFriendlyURL_mjs.getFriendlyURL(possibleUrl.toString())); + } + return possibleUrl.href; + } + } + + return null; +}; + +const moduleExports = {}; + +/** + * Add items to the precache list, removing any duplicates and + * store the files in the + * ["precache cache"]{@link module:workbox-core.cacheNames} when the service + * worker installs. + * + * This method can be called multiple times. + * + * Please note: This method **will not** serve any of the cached files for you, + * it only precaches files. To respond to a network request you call + * [addRoute()]{@link module:workbox-precaching.addRoute}. + * + * If you have a single array of files to precache, you can just call + * [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}. + * + * @param {Array<Object|string>} entries Array of entries to precache. + * + * @alias workbox.precaching.precache + */ +moduleExports.precache = entries => { + precacheController.addToCacheList(entries); + + if (installActivateListenersAdded || entries.length <= 0) { + return; + } + + installActivateListenersAdded = true; + self.addEventListener('install', event => { + event.waitUntil(precacheController.install({ + suppressWarnings, + plugins + })); + }); + self.addEventListener('activate', event => { + event.waitUntil(precacheController.activate({ + plugins + })); + }); +}; + +/** + * Add a `fetch` listener to the service worker that will + * respond to + * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests} + * with precached assets. + * + * Requests for assets that aren't precached, the `FetchEvent` will not be + * responded to, allowing the event to fall through to other `fetch` event + * listeners. + * + * @param {Object} options + * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will + * check cache entries for a URLs ending with '/' to see if there is a hit when + * appending the `directoryIndex` value. + * @param {Array<RegExp>} [options.ignoreUrlParametersMatching=[/^utm_/]] An + * array of regex's to remove search params when looking for a cache match. + * @param {boolean} [options.cleanUrls=true] The `cleanUrls` option will + * check the cache for the URL with a `.html` added to the end of the end. + * @param {workbox.precaching~urlManipulation} [options.urlManipulation] + * This is a function that should take a URL and return an array of + * alternative URL's that should be checked for precache matches. + * + * @alias workbox.precaching.addRoute + */ +moduleExports.addRoute = options => { + if (fetchListenersAdded) { + // TODO: Throw error here. + return; + } + + fetchListenersAdded = true; + self.addEventListener('fetch', event => { + const precachedUrl = _getPrecachedUrl(event.request.url, options); + if (!precachedUrl) { + { + logger_mjs.logger.debug(`Precaching found no match for ` + getFriendlyURL_mjs.getFriendlyURL(event.request.url)); + } + return; + } + + let responsePromise = caches.open(cacheName).then(cache => { + return cache.match(precachedUrl); + }).then(cachedResponse => { + if (cachedResponse) { + return cachedResponse; + } + + // Fall back to the network if we don't have a cached response (perhaps + // due to manual cache cleanup). + { + logger_mjs.logger.debug(`The precached response for ` + `${getFriendlyURL_mjs.getFriendlyURL(precachedUrl)} in ${cacheName} was not found. ` + `Falling back to the network instead.`); + } + + return fetch(precachedUrl); + }); + + { + responsePromise = responsePromise.then(response => { + // Workbox is going to handle the route. + // print the routing details to the console. + logger_mjs.logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL_mjs.getFriendlyURL(event.request.url)); + logger_mjs.logger.log(`Serving the precached url: ${precachedUrl}`); + + // The Request and Response objects contains a great deal of + // information, hide it under a group in case developers want to see it. + logger_mjs.logger.groupCollapsed(`View request details here.`); + logger_mjs.logger.unprefixed.log(event.request); + logger_mjs.logger.groupEnd(); + + logger_mjs.logger.groupCollapsed(`View response details here.`); + logger_mjs.logger.unprefixed.log(response); + logger_mjs.logger.groupEnd(); + + logger_mjs.logger.groupEnd(); + return response; + }); + } + event.respondWith(responsePromise); + }); +}; + +/** + * This method will add entries to the precache list and add a route to + * respond to fetch events. + * + * This is a convenience method that will call + * [precache()]{@link module:workbox-precaching.precache} and + * [addRoute()]{@link module:workbox-precaching.addRoute} in a single call. + * + * @param {Array<Object|string>} entries Array of entries to precache. + * @param {Object} options See + * [addRoute() options]{@link module:workbox-precaching.addRoute}. + * + * @alias workbox.precaching.precacheAndRoute + */ +moduleExports.precacheAndRoute = (entries, options) => { + moduleExports.precache(entries); + moduleExports.addRoute(options); +}; + +/** + * Warnings will be logged if any of the precached assets are entered without + * a `revision` property. This is extremely dangerous if the URL's aren't + * revisioned. However, the warnings can be supressed with this method. + * + * @param {boolean} suppress + * + * @alias workbox.precaching.suppressWarnings + */ +moduleExports.suppressWarnings = suppress => { + suppressWarnings = suppress; +}; + +/** + * Add plugins to precaching. + * + * @param {Array<Object>} newPlugins + * + * @alias workbox.precaching.addPlugins + */ +moduleExports.addPlugins = newPlugins => { + plugins = plugins.concat(newPlugins); +}; + +/* + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +const finalExport = Object.assign(moduleExports, publicAPI); + +return finalExport; + +}(workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private)); + +//# sourceMappingURL=workbox-precaching.dev.js.map |
