Skip to content

Commit 82390f8

Browse files
authored
Pause prefetches when non-prefetch request is sent to origin (#45)
* Pause prefetches when non-prefetch request is sent to origin * Add testing framework for service worker bootstrap * Add rewire to help with testing service worker bootstrap * Resume prefetches when fetch throws an error * Use async/await in service worker fetch handler
1 parent 000477a commit 82390f8

File tree

6 files changed

+240
-29
lines changed

6 files changed

+240
-29
lines changed

package-lock.json

Lines changed: 92 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"@storybook/react": "^5.2.6",
7272
"@svgr/webpack": "^4.3.3",
7373
"babel-loader": "^8.0.6",
74+
"babel-plugin-rewire": "^1.2.0",
7475
"babel-plugin-transform-imports": "^2.0.0",
7576
"create-index": "^2.5.0",
7677
"documentation": "moovweb/documentation#feature/preserve-markdown",
@@ -87,6 +88,7 @@
8788
"react": "^16.8.0",
8889
"react-docgen": "^5.1.0",
8990
"react-dom": "^16.8.0",
91+
"service-worker-mock": "^2.0.5",
9092
"sync-folders": "^2.0.0",
9193
"yalc": "^1.0.0-pre.34"
9294
},
@@ -146,10 +148,14 @@
146148
"collectCoverage": true,
147149
"collectCoverageFrom": [
148150
"./src/**/*.{js,jsx}",
151+
"./service-worker/*.{js,jsx}",
149152
"!**/index.js"
150153
],
151154
"moduleNameMapper": {
152155
"react-storefront/(.*)": "<rootDir>/src/$1"
156+
},
157+
"transform": {
158+
".*": "./test/config/babelTransformer.js"
153159
}
154160
}
155161
}

service-worker/bootstrap.js

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ workbox.loadModule('workbox-strategies')
44

55
const PREFETCH_CACHE_MISS = 412
66

7-
// If we used anything other than a 2xx status, chrome console will show a
8-
// failed fetch every time there is a cache miss. If we return null, workbox
9-
// will show a warning and chrome console will show a fetch failure.
10-
const CLIENT_CACHE_MISS = 204
11-
127
let runtimeCacheOptions = {}
138
let abortControllers = new Set()
149
let toResume = new Set()
@@ -28,7 +23,6 @@ try {
2823
/**
2924
* Configures parameters for cached routes.
3025
* @param {Object} options
31-
* @param {Object} options.cacheName The name of the runtime cache
3226
* @param {Object} options.maxEntries The max number of entries to store in the cache
3327
* @param {Object} options.maxAgeSeconds The TTL in seconds for entries
3428
*/
@@ -67,7 +61,7 @@ function precacheLinks(response) {
6761

6862
/**
6963
* Fetches and caches the specified path.
70-
* @param {Object} options A URL path
64+
* @param {Object} options Cache path options
7165
* @param {String} options.path A URL path
7266
* @param {String} options.apiVersion The version of the api that the client is running
7367
* @param {Boolean} cacheLinks Set to true to fetch and cache all links in the HTML returned
@@ -137,7 +131,9 @@ function abortPrefetches() {
137131
abortControllers.clear()
138132
}
139133

140-
/** Resume queued prefetch requests which were cancelled to allow for more important requests */
134+
/**
135+
* Resume queued prefetch requests which were cancelled to allow for more important requests
136+
*/
141137
function resumePrefetches() {
142138
console.log('[react-storefront service worker] resuming prefetches')
143139
for (let args of toResume) {
@@ -169,9 +165,9 @@ function addToCache(cache, path, data, contentType) {
169165

170166
/**
171167
* Adds the specified data to the cache
172-
* @param {Object} options A URL path
168+
* @param {Object} options Cache state options
173169
* @param {String} options.path A URL path
174-
* @param {Boolean} options.cacheData The data to cache
170+
* @param {Object|String} options.cacheData The data to cache. Objects will be converted to JSON.
175171
* @param {String} options.apiVersion The version of the api that the client is running.
176172
*/
177173
function cacheState({ path, cacheData, apiVersion } = {}) {
@@ -249,6 +245,23 @@ self.addEventListener('install', event => {
249245
})
250246
})
251247

248+
self.addEventListener('fetch', event => {
249+
// Catches all non-prefetch requests and aborts in-progress prefetches
250+
// until the request finishes, then resumes prefetching
251+
abortPrefetches()
252+
event.respondWith(
253+
(async function() {
254+
try {
255+
return await fetch(event.request)
256+
} finally {
257+
if (toResume.size) {
258+
resumePrefetches()
259+
}
260+
}
261+
})(),
262+
)
263+
})
264+
252265
/**
253266
* Returns true if the URL uses https
254267
* @param {Object} context
@@ -276,21 +289,6 @@ function isAmp(url) {
276289
return !!url.pathname.match(/\.amp$/)
277290
}
278291

279-
/**
280-
* Only deliver HTML from the cache when transitioning from AMP or launching from the homescreen.
281-
* @param {String} url The url being fetched
282-
* @param {Event} event The fetch event
283-
* @return {Boolean}
284-
*/
285-
function shouldServeHTMLFromCache(url, event) {
286-
return (
287-
'{{serveSSRFromCache}}' === 'true' ||
288-
isAmp({ pathname: event.request.referrer }) ||
289-
/\?source=pwa/.test(url.search) ||
290-
/(\?|&)powerlink/.test(url.search)
291-
)
292-
}
293-
294292
/**
295293
* Returns true of the request is for a video file
296294
* @param {Object} context

0 commit comments

Comments
 (0)