mirror of
https://github.com/hanzoai/workbox.git
synced 2026-09-24 17:04:35 +00:00
Workbox microsite + gulp task instead of npm-publish-scripts (#518)
* Workbox microsite + gulp task instead of npm-publish-scripts * Fixing merge conflict * Patching up the linting errors in the project
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
third_party
|
||||
/_site/
|
||||
+1
-3
@@ -2,11 +2,9 @@
|
||||
.DS_Store
|
||||
build
|
||||
docs/Gemfile*
|
||||
docs/_*
|
||||
docs/reference-docs
|
||||
docs/themes
|
||||
lerna-debug.log
|
||||
node_modules
|
||||
npm-debug.log
|
||||
packages/**/LICENSE
|
||||
temp
|
||||
/_site/
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
source "http://rubygems.org"
|
||||
|
||||
gem 'jekyll', '>=3.1.6'
|
||||
gem 'kramdown'
|
||||
gem 'jekyll-github-metadata'
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"require-jsdoc": 0,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
- title: Getting Started
|
||||
url: /
|
||||
- title: sw-cli
|
||||
url: /sw-cli
|
||||
- title: sw-build
|
||||
url: /sw-build
|
||||
- title: sw-lib
|
||||
url: /sw-lib
|
||||
- title: Recipes
|
||||
dropdown:
|
||||
- title: Web Pack
|
||||
url: /recipes/webpack
|
||||
- title: Gulp
|
||||
url: /recipes/gulp
|
||||
- title: Rollup
|
||||
url: /recipes/rollup
|
||||
- title: Grunt
|
||||
url: /recipes/grunt
|
||||
- title: Examples
|
||||
url: /examples
|
||||
- title: Reference
|
||||
dropdown:
|
||||
- title: sw-background-sync-queue
|
||||
url: /reference-docs/stable/latest/module-sw-background-sync-queue.html
|
||||
- title: sw-broadcast-cache-update
|
||||
url: /reference-docs/stable/latest/module-sw-broadcast-cache-update.html
|
||||
- title: sw-build
|
||||
url: /reference-docs/stable/latest/module-sw-build.html
|
||||
- title: sw-cache-expiration
|
||||
url: /reference-docs/stable/latest/module-sw-cache-expiration.html
|
||||
- title: sw-cacheable-response
|
||||
url: /reference-docs/stable/latest/module-sw-cacheable-response.html
|
||||
- title: sw-lib
|
||||
url: /reference-docs/stable/latest/module-sw-lib.html
|
||||
- title: sw-offline-google-analytics
|
||||
url: /reference-docs/stable/latest/module-sw-offline-google-analytics.html
|
||||
- title: sw-precaching
|
||||
url: /reference-docs/stable/latest/module-sw-precaching.html
|
||||
- title: sw-routing
|
||||
url: /reference-docs/stable/latest/module-sw-routing.html
|
||||
- title: sw-runtime-caching
|
||||
url: /reference-docs/stable/latest/module-sw-runtime-caching.html
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
layout: page
|
||||
title: Recipes > Grunt
|
||||
---
|
||||
|
||||
# Grunt
|
||||
|
||||
Need to write up.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
layout: page
|
||||
title: Recipes > Gulp
|
||||
---
|
||||
|
||||
# Gulp
|
||||
|
||||
Need to write up.
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
layout: index
|
||||
title: Recipes
|
||||
navigation_weight: 4
|
||||
---
|
||||
|
||||
# Recipes
|
||||
|
||||
You can think of recipes as short guides explaining how to achieve a
|
||||
more specific / niche task like, how do can you generate a service work
|
||||
with gulp?
|
||||
|
||||
> Find a list of available recipes in the side nav.
|
||||
|
||||
If there is a recipe that you think should exist
|
||||
[please raise an issue](https://github.com/GoogleChrome/sw-helpers/issues).
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
layout: index
|
||||
title: Rollup Bundling
|
||||
navigation_weight: 1
|
||||
layout: page
|
||||
title: Recipes > Rollup Bundling
|
||||
---
|
||||
|
||||
# Rollup-based Bundling
|
||||
# Rollup Bundling
|
||||
|
||||
These recipes cover the following `sw-lib` use case:
|
||||
- You want to write and maintain your own `sw.js` file that uses precaching via
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
layout: page
|
||||
title: Recipes > Webpack
|
||||
---
|
||||
|
||||
# Webpack
|
||||
|
||||
Need to write up.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,773 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: SWCli"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>SWCli</h2>
|
||||
|
||||
<p>This class is a wrapper to make test easier. This is used by
|
||||
./bin/index.js to pass in the args when the CLI is used.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="_generateBuildManifest"><span class="this">this.</span>_generateBuildManifest<span class="signature">(<span class="signature-args"></span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise</span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Generates a file manifest with revisioning details
|
||||
that can be used in your service worker for precaching assets.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>Resolves when the node process exits.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="_generateSW"><span class="this">this.</span>_generateSW<span class="signature">(<span class="signature-args"></span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise</span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>This method will generate a working service worker with a file manifest.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>The promise returned here will be used to exit the
|
||||
node process cleanly or not.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handleCommand"><span class="this">this.</span>handleCommand<span class="signature">(<span class="signature-args">command, args, flags</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise</span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>If a command is given in the command line args, this method will handle
|
||||
the appropriate action.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">command</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The command name.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">args</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The arguments given to this command.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">flags</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The flags supplied with the command line.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>A promise for the provided task.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handleFlag"><span class="this">this.</span>handleFlag<span class="signature">(<span class="signature-args">flags</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise</span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>If there is no command given to the CLI then the flags will be passed
|
||||
to this function in case a relevant action can be taken.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">flags</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The available flags = require(the command line.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>returns a promise once handled.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="printHelpText"><span class="this">this.</span>printHelpText<span class="signature">(<span class="signature-args"></span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Prints the help text to the terminal.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Reference Docs"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3> </h3>
|
||||
@@ -0,0 +1,131 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-appcache-behavior"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-appcache-behavior">sw-appcache-behavior</h1>
|
||||
<p>A service worker implementation of the behavior defined in a page's App
|
||||
Cache manifest.</p>
|
||||
<p>In your web page you need to add the client-runtime.js file:</p>
|
||||
<pre class="prettyprint source"><code><script src="../build/client-runtime.js"
|
||||
data-service-worker="service-worker.js"></script></code></pre><p>Then in your servier worker you must import the appcache-behavior-import.js
|
||||
file:</p>
|
||||
<pre class="prettyprint source"><code>importScripts('../build/appcache-behavior-import.js');
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
event.respondWith(goog.appCacheBehavior.fetch(event));
|
||||
});</code></pre></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-background-sync-queue"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-background-sync-queue">sw-background-sync-queue</h1>
|
||||
<p>Queues failed requests and uses the Background Sync API to replay those
|
||||
requests at a later time when the network state has changed.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
+583
@@ -0,0 +1,583 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: BroadcastCacheUpdate"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>BroadcastCacheUpdate</h2>
|
||||
|
||||
<p>Can be used to compare two <a href="https://developer.mozilla.org/en-US/docs/Web/API/Response">Responses</a>
|
||||
and uses the <a href="https://developers.google.com/web/updates/2016/09/broadcastchannel">Broadcast Channel API</a>
|
||||
to notify interested parties when those responses differ.</p>
|
||||
<p>For efficiency's sake, the underlying response bodies are not compared;
|
||||
only specific response headers are checked.</p>
|
||||
<p>This class can be used inside any service worker, without having to use any
|
||||
of the other modules in this repo.</p>
|
||||
<p>If you'd like to use this functionality but are already using <code>sw-lib</code> or
|
||||
<code>sw-runtime-caching</code>, then please see the corresponding plugin,
|
||||
<code>BroadcastCacheUpdatePlugin</code>, for a easy integration.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<p class="code-caption">Using BroadcastCacheUpdate when you're handling your
|
||||
own fetch and request logic.</p>
|
||||
|
||||
<pre class="prettyprint"><code>const url = '/path/to/file';
|
||||
const cacheName = 'my-runtime-cache';
|
||||
const bcu = new goog.broadcastCacheUpdate.BroadcastCacheUpdate(
|
||||
{channelName: 'cache-updates'});
|
||||
|
||||
Promise.all([
|
||||
caches.open(cacheName).then((cache) => cache.match(url)),
|
||||
fetch(url),
|
||||
]).then(([first, second]) => {
|
||||
if (first) {
|
||||
bcu.notifyIfUpdated({cacheName, first, second});
|
||||
}
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="BroadcastCacheUpdate">new BroadcastCacheUpdate<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Dispatches cache update messages when a cached response has been updated.
|
||||
Messages will be dispatched on a broadcast channel with the name provided
|
||||
as channelName parameter in the constructor.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">channelName</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The name that will be used when creating
|
||||
the <code>BroadcastChannel</code>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">headersToCheck</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<string></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>A list of headers that will be
|
||||
used to determine whether the responses differ. Defaults to
|
||||
<code>['content-length', 'etag', 'last-modified']</code>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">source</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An attribution value that indicates where
|
||||
the update originated. Defaults to 'sw-broadcast-cache-update'.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="notifyIfUpdated"><span class="this">this.</span>notifyIfUpdated<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>An explicit method to call from your own code to trigger the comparison of
|
||||
two <a href="https://developer.mozilla.org/en-US/docs/Web/API/Response">Responses</a>
|
||||
and fire off a notification via the
|
||||
<a href="https://developers.google.com/web/updates/2016/09/broadcastchannel">Broadcast Channel API</a>
|
||||
if they differ.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The input object to this function.</p>
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">first</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Response</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>One of the responses to compare.
|
||||
This should not be an <a href="http://stackoverflow.com/questions/39109789">opaque response</a>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">second</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Response</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Another of the respones to compare.
|
||||
This should not be an <a href="http://stackoverflow.com/questions/39109789">opaque response</a>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">cacheName</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Name of the cache the responses belong to.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: BroadcastCacheUpdatePlugin"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>BroadcastCacheUpdatePlugin</h2>
|
||||
|
||||
<p>Can be used to compare two <a href="https://developer.mozilla.org/en-US/docs/Web/API/Response">Responses</a>
|
||||
and uses the <a href="https://developers.google.com/web/updates/2016/09/broadcastchannel">Broadcast Channel API</a>
|
||||
to notify interested parties when those responses differ.</p>
|
||||
<p>For efficiency's sake, the underlying response bodies are not compared;
|
||||
only specific response headers are checked.</p>
|
||||
<p>This class is meant to be automatically invoked as a plugin to a
|
||||
<a href="module-sw-runtime-caching.RequestWrapper.html#main">RequestWrapper</a>, which is
|
||||
used by the <code>sw-lib</code> and <code>sw-runtime-caching</code> modules.</p>
|
||||
<p>If you would like to use this functionality outside of the <code>RequestWrapper</code>
|
||||
context, please use the <code>BroadcastCacheUpdate</code> class directly.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<p class="code-caption">Added as a "plugin" to a `RequestWrapper` to
|
||||
automatically dispatch messages on a cache update</p>
|
||||
|
||||
<pre class="prettyprint"><code>const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
cacheName: 'runtime-cache',
|
||||
plugins: [
|
||||
new goog.broadcastCacheUpdate.Plugin({channelName: 'cache-updates'})
|
||||
]
|
||||
});
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
match: ({url}) => url.domain === 'example.com',
|
||||
handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper})
|
||||
});</code></pre>
|
||||
@@ -0,0 +1,846 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-broadcast-cache-update"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-broadcast-cache-update">sw-broadcast-cache-update</h1>
|
||||
<p>A helper library that uses the Broadcast Channel API to announce when
|
||||
two Response objects differ.</p>
|
||||
<p>The main use of this module will be instantiating a new
|
||||
<code>BroadcastCacheUpdatePlugin</code> and passing it to a
|
||||
<a href="module-sw-runtime-caching.RequestWrapper.html#main">RequestWrapper</a>,
|
||||
as shown in the first example below.</p>
|
||||
<p>You can listen for updates from your web app by adding an event listener on
|
||||
a <code>BroadcastChannel</code> within a page, using the same channel name as
|
||||
what's used within the service worker, as shown in the second example below.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Examples</h5>
|
||||
|
||||
<p class="code-caption">Using the BroadcastCacheUpdatePlugin class in a
|
||||
service worker.</p>
|
||||
|
||||
<pre class="prettyprint"><code>const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
cacheName: 'text-files',
|
||||
plugins: [
|
||||
new goog.broadcastCacheUpdate.BroadcastCacheUpdatePlugin(
|
||||
{channelName: 'cache-updates'})
|
||||
],
|
||||
});
|
||||
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: /\.txt$/,
|
||||
handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper}),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
<p class="code-caption">Listening for the broadcast message in the
|
||||
window.</p>
|
||||
|
||||
<pre class="prettyprint"><code>const updateChannel = new BroadcastChannel('cache-updates');
|
||||
updateChannel.addEventListener('message', event => {
|
||||
console.log(`Cache updated: ${event.data.payload.updatedUrl}`);
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Classes</h2>
|
||||
|
||||
<div class="subsection-classes">
|
||||
<dl>
|
||||
<dt><a href="module-sw-broadcast-cache-update.BroadcastCacheUpdate.html#main">BroadcastCacheUpdate</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-broadcast-cache-update.BroadcastCacheUpdatePlugin.html#main">BroadcastCacheUpdatePlugin</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Member Variables</h2>
|
||||
|
||||
<div class="subsection-members">
|
||||
|
||||
|
||||
<div class="collapsing-entry member-type-member">
|
||||
<h4 class="js-collapse-title" id=".cacheUpdatedMessageType"><span class="type-attribs">(static, constant) </span>cacheUpdatedMessageType <span class="return-arrow">→</span> <span class="type-signature">string</span></h4>
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The value <code>'CACHE_UPDATED'</code>, used as the <code>type</code> field of the update message.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>// Prints 'CACHE_UPDATED'
|
||||
console.log(goog.broadcastCacheUpdate.cacheUpdatedMessageType);</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id=".broadcastUpdate"><span class="type-attribs">(static) </span><span class="this">this.</span>broadcastUpdate<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>You would not normally call this method directly; it's called automatically
|
||||
by an instance of the BroadcastCacheUpdate class. It's exposed here
|
||||
for the benefit of developers who would rather not use the full
|
||||
<code>BroadcastCacheUpdate</code> implementation.</p>
|
||||
<p>Calling this will dispatch a message on the provided <a href="https://developers.google.com/web/updates/2016/09/broadcastchannel">Broadcast Channel</a>
|
||||
to notify interested subscribers about a change to a cached resource.</p>
|
||||
<p>The message that's posted has a formation inspired by the
|
||||
<a href="https://github.com/acdlite/flux-standard-action#introduction">Flux standard action</a>
|
||||
format like so:</p>
|
||||
<pre class="prettyprint source"><code>{
|
||||
type: 'CACHE_UPDATED',
|
||||
meta: 'sw-broadcast-cache-update',
|
||||
payload: {
|
||||
cacheName: 'the-cache-name',
|
||||
updatedUrl: 'https://example.com/'
|
||||
}
|
||||
}</code></pre><p>(Usage of <a href="https://facebook.github.io/flux/">Flux</a> itself is not at
|
||||
all required.)</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>goog.broadcastCacheUpdate.broadcastUpdate({
|
||||
channel: new BroadcastChannel('Channel Name'),
|
||||
cacheName: 'example-cache-name',
|
||||
url: '/',
|
||||
source: 'custom-library'
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">channel</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">BroadcastChannel</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The <code>BroadcastChannel</code> to use.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">cacheName</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The name of the cache in which the updated
|
||||
<code>Response</code> was stored.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">url</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The URL associated with the updated <code>Response</code>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">source</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>A string identifying this library as the source
|
||||
of the update message.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id=".responsesAreSame"><span class="type-attribs">(static) </span><span class="this">this.</span>responsesAreSame<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> boolean</span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Given two <code>Response</code>s, compares several header values to see if they are
|
||||
the same or not.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>const responseIsSame = responsesAreSame({
|
||||
first: firstResponse,
|
||||
second: secondResponse,
|
||||
headersToCheck: [
|
||||
'content-length',
|
||||
'etag',
|
||||
'last-modified',
|
||||
]
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">first</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Response</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>One of the <code>Response</code>s.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">second</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Response</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Another of the <code>Response</code>s.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">headersToCheck</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<string></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>A list of headers that will be
|
||||
used to determine whether the <code>Response</code>s differ.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">boolean</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>Whether or not the <code>Response</code> objects are assumed to be
|
||||
the same.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-cache-expiration"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-cache-expiration">sw-cache-expiration</h1>
|
||||
<p>The cache expiration plugin allows you define an expiration and/or
|
||||
limit on the responses cached.</p>
|
||||
<p>This can be used to ensure that responses aren't used when they are stale
|
||||
and that the cache size doesn't grow endlessly.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Examples</h5>
|
||||
|
||||
<p class="code-caption">Used as an automatically invoked "plugin".</p>
|
||||
|
||||
<pre class="prettyprint"><code>// Add cache expiration plugin to `RequestWrapper`.
|
||||
const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
cacheName: 'runtime-cache',
|
||||
plugins: [
|
||||
// The cache size will be capped at 10 entries.
|
||||
new goog.cacheExpiration.Plugin({maxEntries: 10})
|
||||
]
|
||||
});
|
||||
|
||||
// Add `RequestWrapper` to a runtime cache handler.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
match: ({url}) => url.domain === 'example.com',
|
||||
handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper})
|
||||
});</code></pre>
|
||||
|
||||
<p class="code-caption">To use the cache expiration as it's own module, you can
|
||||
call the <code>expireEntries()</code> method to clean up the cache.</p>
|
||||
|
||||
<pre class="prettyprint"><code>expirationPlugin.expireEntries({
|
||||
cacheName: 'example-cache-name'
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Classes</h2>
|
||||
|
||||
<div class="subsection-classes">
|
||||
<dl>
|
||||
<dt><a href="module-sw-cache-expiration.Plugin.html#main">Plugin</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -0,0 +1,287 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: Plugin"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Plugin</h2>
|
||||
|
||||
<p>Use this plugin to cache responses with certain HTTP status codes or
|
||||
header values.</p>
|
||||
<p>Defining both status codes and headers will cache requests with a matching
|
||||
status code and a matching header.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>new goog.cacheableResponse.Plugin({
|
||||
statuses: [0, 200, 404],
|
||||
headers: {
|
||||
'Example-Header-1': 'Header-Value-1'
|
||||
'Example-Header-2': 'Header-Value-2'
|
||||
}
|
||||
})</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="Plugin">new Plugin<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Creates a new <code>Plugin</code> instance, which stores configuration and logic
|
||||
to determine whether a <code>Response</code> object is cacheable or not.</p>
|
||||
<p>If multiple criteria are present (e.g. both <code>statuses</code> and <code>headers</code>), then
|
||||
the <code>Response</code> needs to meet all of the criteria to be cacheable.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">statuses</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<Number></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The status codes that are
|
||||
checked when determining whether a <code>Response</code> is cacheable.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">headers</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object.<String, String></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The header values that are
|
||||
checked when determining whether a <code>Response</code> is cacheable.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,161 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-cacheable-response"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-cacheable-response">sw-cacheable-response</h1>
|
||||
<p>Given a Response object this behaviour determines whether
|
||||
it's cacheable, based on a specific configuration.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<p class="code-caption">Used as an automatically invoked
|
||||
"plugin".</p>
|
||||
|
||||
<pre class="prettyprint"><code>// The responses will be cached if the response code is 0, 200, or 404, and
|
||||
// will not be cached otherwise.
|
||||
const cacheablePlugin = new goog.cacheableResponse.Plugin({
|
||||
statuses: [0, 200, 404]
|
||||
});
|
||||
|
||||
const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
cacheName: 'runtime-cache',
|
||||
plugins: [
|
||||
cacheablePlugin
|
||||
]
|
||||
});
|
||||
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
match: ({url}) => url.domain === 'example.com',
|
||||
handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper})
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Classes</h2>
|
||||
|
||||
<div class="subsection-classes">
|
||||
<dl>
|
||||
<dt><a href="module-sw-cacheable-response.Plugin.html#main">Plugin</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -0,0 +1,747 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: Router"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Router</h2>
|
||||
|
||||
<p>Adds a friendly API on top of the router from the
|
||||
<a href="module-sw-routing.html#main">sw-routing module</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Examples</h3>
|
||||
|
||||
<p class="code-caption">How to define a simple route with caching
|
||||
strategy.</p>
|
||||
|
||||
<pre class="prettyprint"><code>goog.swlib.router.registerRoute('/about', goog.swlib.cacheFirst());</code></pre>
|
||||
|
||||
<p class="code-caption">How to define a simple route with custom caching
|
||||
strategy.</p>
|
||||
|
||||
<pre class="prettyprint"><code>self.goog.swlib.router.registerRoute('/about', (args) => {
|
||||
// The requested URL
|
||||
console.log(args.url);
|
||||
|
||||
// The FetchEvent to handle
|
||||
console.log(args.event);
|
||||
|
||||
// The parameters from the matching route (Commonly
|
||||
// used with Regex / Express routes).
|
||||
console.log(args.params);
|
||||
|
||||
// Return a promise that resolves with a Response.
|
||||
return fetch(args.url);
|
||||
}));</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="Router">new Router<span class="signature">(<span class="signature-args">revisionedCacheName</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructs a light wrapper on top of the underlying <code>Router</code>.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">revisionedCacheName</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">String</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The cache name used for entries cached
|
||||
via cacheRevisionedAssets().</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="registerNavigationRoute"><span class="this">this.</span>registerNavigationRoute<span class="signature">(<span class="signature-args">url, options</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>A shortcut used to register a <a href="module-sw-routing.NavigationRoute.html#main">module:sw-routing.NavigationRoute</a>
|
||||
instance that will respond to navigation requests using a cache entry for
|
||||
<code>url</code>.</p>
|
||||
<p>This is useful when following the <a href="https://developers.google.com/web/fundamentals/architecture/app-shell#example-html-for-appshell">App Shell pattern</a>,
|
||||
in which the previously cached shell is returned for all navigations.</p>
|
||||
<p>The <code>url</code> value should correspond to an entry that's already in the cache,
|
||||
perhaps a URL that is managed by
|
||||
<a href="module-sw-lib.SWLib.html#cacheRevisionedAssets">module:sw-lib.SWLib#cacheRevisionedAssets</a>. Using a URL that isn't
|
||||
already cached will lead to failed navigations.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">url</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">String</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The URL of the already cached HTML resource.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">options</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">blacklist</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<RegExp></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Defaults to an empty blacklist.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">whitelist</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<RegExp></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Defaults to <code>[/./]</code>, which will
|
||||
match all request URLs.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">cacheName</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">String</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The name of the cache which contains
|
||||
the cached response for <code>url</code>. Defaults to the name of the cache
|
||||
used by cacheRevisionedAssets().</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="registerRoute"><span class="this">this.</span>registerRoute<span class="signature">(<span class="signature-args">capture, handler</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">capture</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">String</span>
|
||||
|
|
||||
|
||||
<span class="param-type">Regex</span>
|
||||
|
|
||||
|
||||
<span class="param-type">Route</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The capture for a route can be one
|
||||
of three types.</p>
|
||||
<ol>
|
||||
<li>It can be an Express style route, like: '/example/:anything/route/'
|
||||
The only gotcha with this is that it will only capture URL's on your
|
||||
origin.</li>
|
||||
<li>A regex that will be tested against request URL's.</li>
|
||||
<li>A <a href="module-sw-lib.SWLib.html#Route">Route</a> instance.</li>
|
||||
</ol>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
|
||||
|
||||
<span class="param-type">Handler</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Called when the route is caught by the
|
||||
capture criteria. The handler argument is ignored if
|
||||
you pass in a Route object, otherwise it's required.
|
||||
If required, provide a function or a runtime caching strategy.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,190 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-lib"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-lib">sw-lib</h1>
|
||||
<p>A high-level library that makes it easier to configure routes with
|
||||
caching strategies as well as manage precaching
|
||||
of assets during the install step of a service worker.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Examples</h5>
|
||||
|
||||
<p class="code-caption">Adding the Library to your project.</p>
|
||||
|
||||
<pre class="prettyprint"><code>importScripts('/<Path to Module>/build/sw-lib.min.js');</code></pre>
|
||||
|
||||
<p class="code-caption">Caching assets and registering routes.</p>
|
||||
|
||||
<pre class="prettyprint"><code>goog.swlib.cacheRevisionedAssets([
|
||||
{
|
||||
url: '/',
|
||||
revision: '1234'
|
||||
},
|
||||
{
|
||||
url: '/styles/main.css',
|
||||
revision: 'abcd'
|
||||
}
|
||||
]);
|
||||
|
||||
// Register runtime routes like so.
|
||||
goog.swlib.router.registerRoute(
|
||||
'/example/', goog.swlib.staleWhileRevalidate());
|
||||
goog.swlib.router.registerRoute(
|
||||
/\/images\/(.*\/)?.*\.(png|jpg|jpeg|gif)/, goog.swlib.cacheFirst());
|
||||
goog.swlib.router.registerRoute(
|
||||
'/styles/:filename', goog.swlib.cacheFirst());</code></pre>
|
||||
|
||||
<p class="code-caption">Using plugins with caching strategies.</p>
|
||||
|
||||
<pre class="prettyprint"><code>goog.swlib.router.registerRoute(/\/images\/(.*\/)?.*\.(png|jpg|jpeg|gif)/,
|
||||
goog.swlib.cacheFirst({
|
||||
cacheName: 'example-cache',
|
||||
cacheExpiration: {
|
||||
maxEntries: 10,
|
||||
maxAgeSeconds: 7 * 24 * 60 * 60
|
||||
},
|
||||
cacheableResponse: {
|
||||
statuses: [0, 200]
|
||||
},
|
||||
broadcastCacheUpdate: {
|
||||
channelName: 'example-channel-name'
|
||||
},
|
||||
plugins: [
|
||||
// Additional Plugins
|
||||
]
|
||||
})
|
||||
);</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Classes</h2>
|
||||
|
||||
<div class="subsection-classes">
|
||||
<dl>
|
||||
<dt><a href="module-sw-lib.Router.html#main">Router</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-lib.SWLib.html#main">SWLib</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -0,0 +1,429 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-offline-google-analytics"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><p>In order to use the library, call<code>goog.offlineGoogleAnalytics.initialize()</code>.
|
||||
It will take care of setting up service worker <code>fetch</code> handlers to ensure
|
||||
that the Google Analytics JavaScript is available offline, and that any
|
||||
Google Analytics requests made while offline are saved (using <code>IndexedDB</code>)
|
||||
and retried the next time the service worker starts up.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Examples</h5>
|
||||
|
||||
<pre class="prettyprint"><code>// This code should live inside your service worker JavaScript, ideally
|
||||
// before any other 'fetch' event handlers are defined:
|
||||
|
||||
// First, import the library into the service worker global scope:
|
||||
importScripts('path/to/offline-google-analytics-import.js');
|
||||
|
||||
// Then, call goog.offlineGoogleAnalytics.initialize():
|
||||
goog.offlineGoogleAnalytics.initialize();
|
||||
|
||||
// At this point, implement any other service worker caching strategies
|
||||
// appropriate for your web app.</code></pre>
|
||||
|
||||
<pre class="prettyprint"><code>// If you need to specify parameters to be sent with each hit, you can use
|
||||
// the `parameterOverrides` configuration option. This is useful in cases
|
||||
// where you want to set a custom dimension on all hits sent by the service
|
||||
// worker to differentiate them in your reports later.
|
||||
goog.offlineGoogleAnalytics.initialize({
|
||||
parameterOverrides: {
|
||||
cd1: 'replay'
|
||||
}
|
||||
});</code></pre>
|
||||
|
||||
<pre class="prettyprint"><code>// In situations where you need to programmatically modify a hit's
|
||||
// parameters you can use the `hitFilter` option. One example of when this
|
||||
// might be useful is if you wanted to track the amount of time that elapsed
|
||||
// between when the hit was attempted and when it was successfully replayed.
|
||||
goog.offlineGoogleAnalytics.initialize({
|
||||
hitFilter: searchParams =>
|
||||
// Sets the `qt` param as a custom metric.
|
||||
const qt = searchParams.get('qt');
|
||||
searchParams.set('cm1', qt);
|
||||
}
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id=".goog.offlineGoogleAnalytics.initialize"><span class="type-attribs">(static) </span><span class="this">this.</span>goog.offlineGoogleAnalytics.initialize<span class="signature">(<span class="signature-args">config</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">config</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">parameterOverrides</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p><a href="https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters">Measurement Protocol parameters</a>,
|
||||
expressed as key/value pairs, to be added to replayed
|
||||
Google Analytics requests. This can be used to, e.g., set
|
||||
a custom dimension indicating that the request was
|
||||
replayed.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">hitFilter</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>A function that allows you to modify the hit parameters
|
||||
prior to replaying the hit. The function is invoked with
|
||||
the original hit's URLSearchParams object as its only
|
||||
argument. To abort the hit and prevent it from being
|
||||
replayed, throw an error.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-precaching"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-precaching">sw-precaching</h1>
|
||||
<p>The precaching module provides helpers that make it easy to cache files
|
||||
during the install step of your service worker.</p>
|
||||
<p>The revisioned caching will cache bust requests where appropriate and
|
||||
only cache assets that have a changed revision asset compared to
|
||||
the currently cached value.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>importScripts('/<Path to Module>/build/sw-precaching.min.js');
|
||||
|
||||
const revCacheManager = new goog.precaching.RevisionedCacheManager();
|
||||
revCacheManager.addToCacheList({
|
||||
revisionedFiles: [
|
||||
'/styles/main.1234.css',
|
||||
{
|
||||
url: '/',
|
||||
revision: '1234'
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
const unrevCacheManager = new goog.precaching.UnrevisionedCacheManager();
|
||||
unrevCacheManager.addToCacheList({
|
||||
unrevisionedFiles: [
|
||||
'/',
|
||||
'/images/logo.png'
|
||||
]
|
||||
});
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
const promiseChain = Promise.all([
|
||||
revCacheManager.install(),
|
||||
unrevCacheManager.install(),
|
||||
]);
|
||||
event.waitUntil(promiseChain);
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
const promiseChain = Promise.all([
|
||||
revCacheManager.cleanup(),
|
||||
unrevCacheManager.cleanup()
|
||||
]);
|
||||
event.waitUntil(promiseChain);
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,340 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: ExpressRoute"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>ExpressRoute <span class="extends">extends</span> Route</span>
|
||||
</h2>
|
||||
|
||||
<p><code>ExpressRoute</code> is a helper class to make defining Express-style
|
||||
Routes easy.</p>
|
||||
<p>Under the hood, it uses the <a href="https://www.npmjs.com/package/path-to-regexp"><code>path-to-regexp</code></a>
|
||||
library to transform the <code>path</code> parameter into a regular expression, which is
|
||||
then matched against the URL's path.</p>
|
||||
<p>Please note that <code>ExpressRoute</code> can only match requests for URLs that are on
|
||||
the same-origin as the current page. If you need to match cross-origin
|
||||
requests, you can use either a generic <code>Route</code> or a
|
||||
<code>RegExpRoute</code>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Any same-origin requests that start with /path/to and end with one
|
||||
// additional path segment will match this route, with the last path
|
||||
// segment passed along to the handler via params.file.
|
||||
const route = new goog.routing.ExpressRoute({
|
||||
path: '/path/to/:file',
|
||||
handler: {
|
||||
handle: ({event, params}) => {
|
||||
// params.file will be set based on the request URL that matched.
|
||||
// Do something that returns a Promise.<Response>, like:
|
||||
return caches.match(event.request);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="ExpressRoute">new ExpressRoute<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructor for ExpressRoute.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">path</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The path to use for routing.
|
||||
If the path contains <a href="https://github.com/pillarjs/path-to-regexp#named-parameters">named parameters</a>,
|
||||
then an Object mapping parameter names to the corresponding value
|
||||
will be passed to the handler via <code>params</code>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An Object with a <code>handle</code> method that
|
||||
will be used to respond to matching requests.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">method</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Only match requests that use this
|
||||
HTTP method. Defaults to <code>'GET'</code> if not specified.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,335 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: NavigationRoute"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>NavigationRoute <span class="extends">extends</span> Route</span>
|
||||
</h2>
|
||||
|
||||
<p>NavigationRoute is a helper class to create a <code>Route</code>
|
||||
that matches browser navigation requests, i.e. requests for a page.</p>
|
||||
<p>It will only match incoming requests whose <a href="https://fetch.spec.whatwg.org/#concept-request-mode"><code>mode</code></a>
|
||||
is set to <code>navigate</code>.</p>
|
||||
<p>You can optionally only apply this route to a subset of navigation requests
|
||||
by using one or both of the <code>blacklist</code> and <code>whitelist</code> parameters. If
|
||||
both lists are provided, and there's a navigation to a URL which matches
|
||||
both, then the blacklist will take precedence and the request will not be
|
||||
matched by this route. The regular expressions in <code>whitelist</code> and <code>blacklist</code>
|
||||
are matched against the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname"><code>pathname</code></a>
|
||||
portion of the requested URL.</p>
|
||||
<p>To match all navigations, use a <code>whitelist</code> array containing a RegExp that
|
||||
matches everything, i.e. <code>[/./]</code>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Any navigation requests that match the whitelist (i.e. URLs whose path
|
||||
// starts with /article/) will be handled with the cache entry for
|
||||
// app-shell.html.
|
||||
const route = new goog.routing.NavigationRoute({
|
||||
whitelist: [new RegExp('^/article/')],
|
||||
handler: {handle: () => caches.match('app-shell.html')},
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="NavigationRoute">new NavigationRoute<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructor for NavigationRoute.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">whitelist</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<RegExp></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>If any of these patterns match,
|
||||
the route will handle the request (assuming the blacklist doesn't match).</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">blacklist</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<RegExp></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>If any of these patterns match,
|
||||
the route will not handle the request (even if a whitelist entry matches).</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The handler to manage the response.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,334 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: RegExpRoute"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>RegExpRoute <span class="extends">extends</span> Route</span>
|
||||
</h2>
|
||||
|
||||
<p>RegExpRoute is a helper class to make defining regular expression based
|
||||
Routes easy.</p>
|
||||
<p><code>RegExpRoute</code> performs its matches against the full request URL, including
|
||||
the origin. This means that, unlike <code>ExpressRoute</code>,
|
||||
it's able to match cross-origin requests.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Any requests that match the regular expression will match this route, with
|
||||
// the capture groups passed along to the handler as an array via params.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: new RegExp('^https://example.com/path/to/(\\w+)'),
|
||||
handler: {
|
||||
handle: ({event, params}) => {
|
||||
// params[0], etc. will be set based on the regexp capture groups.
|
||||
// Do something that returns a Promise.<Response>, like:
|
||||
return caches.match(event.request);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="RegExpRoute">new RegExpRoute<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructor for RegExpRoute.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">regExp</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">RegExp</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The regular expression to match against URLs.
|
||||
If the <code>RegExp</code> contains <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references">capture groups</a>,
|
||||
then the array of captured values will be passed to the handler via
|
||||
<code>params</code>.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The handler to manage the response.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">method</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Only match requests that use this
|
||||
HTTP method. Defaults to <code>'GET'</code> if not specified.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,358 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: Route"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Route</h2>
|
||||
|
||||
<p>A <code>Route</code> allows you to tell a service worker that it should handle
|
||||
certain network requests using a specific response strategy.</p>
|
||||
<p>Two configuration options are required:</p>
|
||||
<ul>
|
||||
<li>A <code>match</code> function, which examines
|
||||
an incoming <a href="https://developer.mozilla.org/en-US/docs/Web/API/Request"><code>Request</code></a>
|
||||
to determine whether this <code>Route</code> should apply. The function should return
|
||||
a <a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy">truthy</a> value
|
||||
if the <code>Route</code> matches, in which case that return value is passed along to
|
||||
the <code>handle</code> function.</li>
|
||||
<li>A <code>handler</code> object, which should in turn have a function defined on it
|
||||
named <code>handle</code>. This <code>handle</code> function is given the incoming request along
|
||||
with any additional parameters generated during the <code>match</code>, and returns a
|
||||
Promise for a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Response"><code>Response</code></a>.</li>
|
||||
</ul>
|
||||
<p>Instead of implementing your own <code>handler</code>, you can use one of the
|
||||
pre-defined runtime caching strategies from the
|
||||
<a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a> module.</p>
|
||||
<p>While you can use <code>Route</code> directly, the <code>RegExpRoute</code>
|
||||
and <code>ExpressRoute</code> subclasses provide a convenient
|
||||
wrapper with a nicer interface for using regular expressions or Express-style
|
||||
routes as the <code>match</code> criteria.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Any navigate requests for URLs that start with /path/to/ will match.
|
||||
const route = new goog.routing.Route({
|
||||
match: ({url, event}) => {
|
||||
return event.request.mode === 'navigate' &&
|
||||
url.pathname.startsWith('/path/to/');
|
||||
},
|
||||
handler: ({event}) => {
|
||||
// Do something that returns a Promise.<Response>, like:
|
||||
return caches.match(event.request);
|
||||
},
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="Route">new Route<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructor for Route class.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">match</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The function that determines whether the
|
||||
route matches. The function is passed an object with two properties:
|
||||
<code>url</code>, which is a <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL">URL</a>,
|
||||
and <code>event</code>, which is a <a href="https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent">FetchEvent</a>.
|
||||
<code>match</code> should return a truthy value when the route applies, and
|
||||
that value is passed on to the handle function.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>A function, or an Object with a
|
||||
<code>handle</code> method. As parameters, the handler is passed an object with
|
||||
the same <code>url</code> and <code>event</code> properties as <code>match</code> received, along
|
||||
with an additional property, <code>params</code>, set to the truthy value
|
||||
<code>match</code> returned.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">method</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Only match requests that use this
|
||||
HTTP method. Defaults to <code>'GET'</code> if not specified.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,928 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: Router"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Router</h2>
|
||||
|
||||
<p>The Router takes one or more Routes and registers a <a href="https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent"><code>fetch</code>
|
||||
event listener</a>
|
||||
that will respond to network requests if there's a matching route.</p>
|
||||
<p>It also allows you to define a "default" handler that applies to any requests
|
||||
that don't explicitly match a <code>Route</code>, and a "catch" handler that responds
|
||||
to any requests that throw an exception while being routed.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// The following example sets up two routes, one to match requests with
|
||||
// "assets" in their URL, and the other for requests with "images", along
|
||||
// different runtime caching handlers for each.
|
||||
// Both the routes are registered with the router, and any requests that
|
||||
// don't match either route will be handled using the default NetworkFirst
|
||||
// strategy.
|
||||
const assetRoute = new RegExpRoute({
|
||||
regExp: /assets/,
|
||||
handler: new goog.runtimeCaching.StaleWhileRevalidate(),
|
||||
});
|
||||
const imageRoute = new RegExpRoute({
|
||||
regExp: /images/,
|
||||
handler: new goog.runtimeCaching.CacheFirst(),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoutes({routes: [assetRoute, imageRoute]});
|
||||
router.setDefaultHandler({handler: new goog.runtimeCaching.NetworkFirst()});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="Router">new Router<span class="signature">(<span class="signature-args"></span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Start with an empty array of routes, and set up the fetch handler.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="registerRoute"><span class="this">this.</span>registerRoute<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Registers a single route with the router.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>router.registerRoutes({
|
||||
route: new Route({ ... })
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">route</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Route</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The route to register.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="registerRoutes"><span class="this">this.</span>registerRoutes<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Register routes will take an array of Routes to register with the
|
||||
router.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>router.registerRoutes({
|
||||
routes: [
|
||||
new RegExpRoute({ ... }),
|
||||
new ExpressRoute({ ... }),
|
||||
new Route({ ... }),
|
||||
]
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">routes</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<Route></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An array of routes to register.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="setCatchHandler"><span class="this">this.</span>setCatchHandler<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>If a Route throws an error while handling a request, this catch handler
|
||||
will be called to return an error case.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>router.setCatchHandler({
|
||||
handler: ({event, params}) => {
|
||||
return caches.match('/error-page.html');
|
||||
}
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An Object with a <code>handle</code> method.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="setDefaultHandler"><span class="this">this.</span>setDefaultHandler<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>An optional default handler will have its handle method called when a
|
||||
request doesn't have a matching route.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h5>Example</h5>
|
||||
|
||||
<pre class="prettyprint"><code>router.setDefaultHandler({
|
||||
handler: new goog.runtimeCaching.NetworkFirst()
|
||||
});</code></pre>
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">handler</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An Object with a <code>handle</code> method.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,148 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-routing"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-routing">sw-routing</h1>
|
||||
<p>A service worker helper library to route request URLs to handlers.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Classes</h2>
|
||||
|
||||
<div class="subsection-classes">
|
||||
<dl>
|
||||
<dt><a href="module-sw-routing.ExpressRoute.html#main">ExpressRoute</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-routing.NavigationRoute.html#main">NavigationRoute</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-routing.RegExpRoute.html#main">RegExpRoute</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-routing.Route.html#main">Route</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-routing.Router.html#main">Router</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -0,0 +1,277 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: CacheFirst"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>CacheFirst <span class="extends">extends</span> Handler</span>
|
||||
</h2>
|
||||
|
||||
<p>An implementation of a <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network">cache-first</a>
|
||||
request strategy.</p>
|
||||
<p>The important thing to note with this caching strategy is that once a
|
||||
response is cached, it will not be updated. This is useful for assets
|
||||
that are revisioned as it caches the asset long term and doesn't waste
|
||||
the user's data.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Set up a route to match any requests made for URLs that end in .txt.
|
||||
// The requests are handled with a cache-first strategy.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: /\.txt$/,
|
||||
handler: new goog.runtimeCaching.CacheFirst(),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handle"><span class="this">this.</span>handle<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise.<Response></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The handle method will be called by the
|
||||
<a href="module-sw-routing.Route.html#main">Route</a> class when a route matches a request.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">event</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">FetchEvent</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The event that triggered the service
|
||||
worker's fetch handler.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise.<Response></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>The response, either from the cache,
|
||||
or if that isn't available, from the network.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,275 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: CacheOnly"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>CacheOnly <span class="extends">extends</span> Handler</span>
|
||||
</h2>
|
||||
|
||||
<p>An implementation of a <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-only">cache-only</a>
|
||||
request strategy.</p>
|
||||
<p>The advantage to using this versus directly calling <code>caches.match()</code> is that
|
||||
it will use the cache configuration and trigger the plugins defined in
|
||||
the underlying <code>RequestWrapper</code>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Set up a route to match any requests made for URLs that end in .txt.
|
||||
// The requests are handled with a cache-only strategy.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: /\.txt$/,
|
||||
handler: new goog.runtimeCaching.CacheOnly(),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handle"><span class="this">this.</span>handle<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise.<Response></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The handle method will be called by the
|
||||
<a href="module-sw-routing.Route.html#main">Route</a> class when a route matches a request.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">event</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">FetchEvent</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The event that triggered the service
|
||||
worker's fetch handler.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise.<Response></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>The response from the cache.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,505 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: Handler"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Handler</h2>
|
||||
|
||||
<p>This a base class which each caching strategy extends.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="Handler">new Handler<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructor for a new Handler instance.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">requestWrapper</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">RequestWrapper</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An optional <code>RequestWrapper</code>
|
||||
that is used to configure the cache name and request plugins. If
|
||||
not provided, a new <code>RequestWrapper</code> using the
|
||||
<a href="#defaultCacheName">default cache name</a> will be used.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handle"><span class="type-attribs">(abstract) </span><span class="this">this.</span>handle<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise.<Response></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>An abstract method that each subclass must implement.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">event</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">FetchEvent</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The event that triggered the service
|
||||
worker's fetch handler.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">params</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>Additional parameters that might be passed
|
||||
in to the method. If used in conjunction with the
|
||||
<a href="module-sw-routing.Route.html#main">Route</a> class, then the return value
|
||||
from the <code>match</code> function in the Route constructor
|
||||
will be passed in as the <code>params</code> value.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise.<Response></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>A promise resolving with a response.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,515 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: NetworkFirst"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>NetworkFirst <span class="extends">extends</span> Handler</span>
|
||||
</h2>
|
||||
|
||||
<p>An implementation of a <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-falling-back-to-cache">network first</a>
|
||||
request strategy.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Set up a route to match any requests made for URLs that end in .txt.
|
||||
// The requests are handled with a network-first strategy.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: /\.txt$/,
|
||||
handler: new goog.runtimeCaching.NetworkFirst(),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Constructor</h2>
|
||||
|
||||
<div class="subsection-constructor">
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-class start-open">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="NetworkFirst">new NetworkFirst<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>Constructor for a new Handler instance.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">networkTimeoutSeconds</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">number</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>If set, and a network
|
||||
response isn't returned timeout is reached, then the cached response
|
||||
will be returned instead. If there is no previously cached response,
|
||||
then an <code>null</code> response will be returned. This option is meant to
|
||||
combat "<a href="https://developers.google.com/web/fundamentals/performance/poor-connectivity/#lie-fi">lie-fi</a>"
|
||||
scenarios.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">requestWrapper</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">RequestWrapper</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-attributes">(Optional)</span>
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>An optional <code>RequestWrapper</code>
|
||||
that is used to configure the cache name and request plugins. If
|
||||
not provided, a new <code>RequestWrapper</code> using the
|
||||
<a href="#defaultCacheName">default cache name</a> will be used.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handle"><span class="this">this.</span>handle<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise.<Response></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The handle method will be called by the
|
||||
<a href="module-sw-routing.Route.html#main">Route</a> class when a route matches a request.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">event</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">FetchEvent</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The event that triggered the service
|
||||
worker's fetch handler.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise.<Response></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>The response from the network, or if that's
|
||||
not available, a previously cached response.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,274 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: NetworkOnly"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>NetworkOnly <span class="extends">extends</span> Handler</span>
|
||||
</h2>
|
||||
|
||||
<p>An implementation of a <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-only">network-only</a>
|
||||
request strategy.</p>
|
||||
<p>The advantage to using this versus directly calling <code>fetch()</code> is that it will
|
||||
trigger the plugins defined in the underlying <code>RequestWrapper</code>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Set up a route to match any requests made for URLs that end in .txt.
|
||||
// The requests are handled with a network-only strategy.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: /\.txt$/,
|
||||
handler: new goog.runtimeCaching.NetworkOnly(),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handle"><span class="this">this.</span>handle<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise.<Response></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The handle method will be called by the
|
||||
<a href="module-sw-routing.Route.html#main">Route</a> class when a route matches a request.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">event</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">FetchEvent</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The event that triggered the service
|
||||
worker's fetch handler.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise.<Response></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>The response from the network.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
File diff suppressed because it is too large
Load Diff
+275
@@ -0,0 +1,275 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Class: StaleWhileRevalidate"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>StaleWhileRevalidate <span class="extends">extends</span> Handler</span>
|
||||
</h2>
|
||||
|
||||
<p>An implementation of a <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate">stale-while-revalidate</a>
|
||||
request strategy.</p>
|
||||
<p>In addition to updating the appropriate caches, it will also trigger any
|
||||
appropriate plugins defined in the underlying <code>RequestWrapper</code>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<pre class="prettyprint"><code>// Set up a route to match any requests made for URLs that end in .txt.
|
||||
// The requests are handled with a stale-while-revalidate strategy.
|
||||
const route = new goog.routing.RegExpRoute({
|
||||
regExp: /\.txt$/,
|
||||
handler: new goog.runtimeCaching.StaleWhileRevalidate(),
|
||||
});
|
||||
|
||||
const router = new goog.routing.Router();
|
||||
router.registerRoute({route});</code></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Instance Methods</h2>
|
||||
|
||||
<div class="subsection-methods">
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-function ">
|
||||
|
||||
|
||||
<h4 class="js-collapse-title" id="handle"><span class="this">this.</span>handle<span class="signature">(<span class="signature-args">input</span>)</span><span class="type-signature"> <span class="return-arrow">→</span> Promise.<Response></span></h4>
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The handle method will be called by the
|
||||
<a href="module-sw-routing.Route.html#main">Route</a> class when a route matches a request.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Parameters</th>
|
||||
<td>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">input</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
|
||||
|
||||
<h6>Properties</h6>
|
||||
|
||||
|
||||
<table class="params">
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name">event</td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">FetchEvent</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td></td>
|
||||
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="description last">
|
||||
<p>The event that triggered the service
|
||||
worker's fetch handler.</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="param-type">Promise.<Response></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
<p>The response from the cache, if present, or
|
||||
from the network if not.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,234 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Module: sw-runtime-caching"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description"><h1 id="sw-runtime-caching">sw-runtime-caching</h1>
|
||||
<p>A service worker helper library that implements various runtime caching
|
||||
strategies.</p>
|
||||
<p>You can learn more about each caching strategy on
|
||||
<a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/">Jake Archibald's blog post</a>
|
||||
which covers various ways of handling fetch events with a service worker.</p></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="collapsing-entry method-type-module ">
|
||||
|
||||
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="method-info-table">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<td>
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Classes</h2>
|
||||
|
||||
<div class="subsection-classes">
|
||||
<dl>
|
||||
<dt><a href="module-sw-runtime-caching.CacheFirst.html#main">CacheFirst</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-runtime-caching.CacheOnly.html#main">CacheOnly</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-runtime-caching.Handler.html#main">Handler</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-runtime-caching.NetworkFirst.html#main">NetworkFirst</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-runtime-caching.NetworkOnly.html#main">NetworkOnly</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-runtime-caching.RequestWrapper.html#main">RequestWrapper</a></dt>
|
||||
<dd></dd>
|
||||
|
||||
<dt><a href="module-sw-runtime-caching.StaleWhileRevalidate.html#main">StaleWhileRevalidate</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="subsection-title">Member Variables</h2>
|
||||
|
||||
<div class="subsection-members">
|
||||
|
||||
|
||||
<div class="collapsing-entry member-type-member">
|
||||
<h4 class="js-collapse-title" id=".cacheName"><span class="type-attribs">(static) </span>cacheName <span class="return-arrow">→</span> <span class="type-signature">string</span></h4>
|
||||
|
||||
<div class="collapse-details js-collapse-details">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
<p>The default cache name, used by
|
||||
<a href="module-sw-runtime-caching.RequestWrapper.html#main">RequestWrapper</a> when there's
|
||||
no name provided.</p>
|
||||
<p>It combines a constant prefix with the <code>registration.scope</code> value associated
|
||||
with the current service worker, ensuring that multiple service workers used
|
||||
on the same origin will have different default caches.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
+558
@@ -0,0 +1,558 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-appcache-behavior/src/appcache-behavior-import.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/* eslint-env worker, serviceworker */
|
||||
|
||||
'use strict';
|
||||
|
||||
import IDBHelper from '../../../lib/idb-helper.js';
|
||||
import logHelper from '../../../lib/log-helper.js';
|
||||
import constants from './lib/constants.js';
|
||||
|
||||
const idbHelpers = {};
|
||||
Object.keys(constants.STORES).forEach((storeId) => {
|
||||
idbHelpers[constants.STORES[storeId]] = new IDBHelper(
|
||||
constants.DB_NAME, constants.DB_VERSION, constants.STORES[storeId]);
|
||||
});
|
||||
|
||||
/**
|
||||
* Determines what the most likely URL is associated with the client page from
|
||||
* which the event's request originates. This is used to determine which
|
||||
* AppCache manifest's rules should be applied.
|
||||
*
|
||||
* @private
|
||||
* @param {FetchEvent} event
|
||||
* @return {Promise.<String>} The client URL
|
||||
*/
|
||||
function getClientUrlForEvent(event) {
|
||||
// If our service worker implementation supports client identifiers, try
|
||||
// to get the client URL using that.
|
||||
return self.clients.get(event.clientId)
|
||||
.then((client) => client.url)
|
||||
// If those aren't supported, .catch() any errors and try something else.
|
||||
.catch((error) => {
|
||||
logHelper.error(
|
||||
'Error while using clients.get(event.clientId).url: ' + error);
|
||||
// Firefox currently sets the referer to 'about:client' for initial
|
||||
// navigations, but that's not useful for our purposes.
|
||||
if (event.request.referrer &&
|
||||
event.request.referrer !== 'about:client') {
|
||||
return event.request.referrer;
|
||||
}
|
||||
|
||||
// Use the event's request URL as the last resort, with the assumption
|
||||
// that this is a navigation request.
|
||||
return event.request.url;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the longest matching prefix, given an array of possible matches.
|
||||
*
|
||||
* @private
|
||||
* @param {Array.<String>} urlPrefixes
|
||||
* @param {String} fullUrl
|
||||
* @return {String} The longest matching prefix, or '' if none match
|
||||
*/
|
||||
function longestMatchingPrefix(urlPrefixes, fullUrl) {
|
||||
return urlPrefixes
|
||||
.filter((urlPrefix) => fullUrl.startsWith(urlPrefix))
|
||||
.reduce((longestSoFar, current) => {
|
||||
return longestSoFar.length >= current.length ? longestSoFar : current;
|
||||
}, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a fetch(), using a cached response as a fallback if that fails.
|
||||
*
|
||||
* @private
|
||||
* @param {Request} request
|
||||
* @param {String} fallbackUrl
|
||||
* @param {String} cacheName
|
||||
* @return {Promise.<Response>}
|
||||
*/
|
||||
function fetchWithFallback(request, fallbackUrl, cacheName) {
|
||||
logHelper.log('Trying fetch for', request.url);
|
||||
return fetch(request).then((response) => {
|
||||
// Succesful but error-like responses are treated as failures.
|
||||
// Ditto for redirects to other origins.
|
||||
if (!response.ok || (new URL(response.url).origin !== location.origin)) {
|
||||
throw Error('Fallback request failure.');
|
||||
}
|
||||
return response;
|
||||
}).catch(() => {
|
||||
logHelper.warn('fetch() failed. Falling back to cache of', fallbackUrl);
|
||||
return caches.open(cacheName).then(
|
||||
(cache) => cache.match(fallbackUrl));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks IndexedDB for a manifest with a given URL. If found, it fulfills
|
||||
* with info about the latest version.
|
||||
*
|
||||
* @private
|
||||
* @param {String} manifestUrl
|
||||
* @return {Promise.<Object>}
|
||||
*/
|
||||
function getLatestManifestVersion(manifestUrl) {
|
||||
return idbHelpers[constants.STORES.MANIFEST_URL_TO_CONTENTS].get(manifestUrl)
|
||||
.then((versions) => {
|
||||
if (versions && versions.length) {
|
||||
return versions[versions.length - 1];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks IndexedDB for a manifest with a given URL, versioned with the
|
||||
* given hash. If found, it fulfills with the parsed manifest.
|
||||
*
|
||||
* @private
|
||||
* @param {String} manifestUrl
|
||||
* @param {String} manifestHash
|
||||
* @return {Promise.<Object>}
|
||||
*/
|
||||
function getParsedManifestVersion(manifestUrl, manifestHash) {
|
||||
return idbHelpers[constants.STORES.MANIFEST_URL_TO_CONTENTS].get(manifestUrl)
|
||||
.then((versions) => {
|
||||
versions = versions || [];
|
||||
logHelper.log('versions is', versions);
|
||||
return versions.reduce((result, current) => {
|
||||
logHelper.log('current is', current);
|
||||
// If we already have a result, just keep returning it.
|
||||
if (result) {
|
||||
logHelper.log('result is', result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, check to see if the hashes match. If so, use the parsed
|
||||
// manifest for the current entry as the result.
|
||||
if (current.hash === manifestHash) {
|
||||
logHelper.log('manifestHash match', current);
|
||||
return current.parsed;
|
||||
}
|
||||
|
||||
return null;
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the CLIENT_ID_TO_HASH store in IndexedDB with the client id to
|
||||
* hash association.
|
||||
*
|
||||
* @private
|
||||
* @param {String} clientId
|
||||
* @param {String} hash
|
||||
* @return {Promise.<T>}
|
||||
*/
|
||||
function saveClientIdAndHash(clientId, hash) {
|
||||
if (clientId) {
|
||||
return idbHelpers[constants.STORES.CLIENT_ID_TO_HASH].put(clientId, hash);
|
||||
}
|
||||
|
||||
// Return a fulfilled Promise so that we can still call .then().
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the actual AppCache logic, given a specific manifest and hash
|
||||
* used as a cache identifier.
|
||||
*
|
||||
* @private
|
||||
* @param {FetchEvent} event
|
||||
* @param {Object} manifest
|
||||
* @param {String} hash
|
||||
* @param {String} clientUrl
|
||||
* @return {Promise.<Response>}
|
||||
*/
|
||||
function appCacheLogic(event, manifest, hash, clientUrl) {
|
||||
logHelper.log('manifest is', manifest, 'version is', hash);
|
||||
const requestUrl = event.request.url;
|
||||
|
||||
// Is our request URL listed in the CACHES section?
|
||||
// Or is our request URL the client URL, since any page that
|
||||
// registers a manifest is treated as if it were in the CACHE?
|
||||
if (manifest.cache.includes(requestUrl) || requestUrl === clientUrl) {
|
||||
logHelper.log('CACHE includes URL; using cache.match()');
|
||||
// If so, return the cached response.
|
||||
return caches.open(hash).then((cache) => cache.match(requestUrl));
|
||||
}
|
||||
|
||||
// Otherwise, check the FALLBACK section next.
|
||||
// FALLBACK keys are URL prefixes, and if more than one prefix
|
||||
// matches our request URL, the longest prefix "wins".
|
||||
// (Of course, it might be that none of the prefixes match.)
|
||||
const fallbackKey = longestMatchingPrefix(Object.keys(manifest.fallback),
|
||||
requestUrl);
|
||||
if (fallbackKey) {
|
||||
logHelper.log('fallbackKey in parsedManifest matches', fallbackKey);
|
||||
return fetchWithFallback(event.request, manifest.fallback[fallbackKey],
|
||||
hash);
|
||||
}
|
||||
|
||||
// If CACHE and FALLBACK don't apply, try NETWORK.
|
||||
if (manifest.network.includes(requestUrl) ||
|
||||
manifest.network.includes('*')) {
|
||||
logHelper.log('Match or * in NETWORK; using fetch()');
|
||||
return fetch(event.request);
|
||||
}
|
||||
|
||||
// If nothing matches, then return an error response.
|
||||
logHelper.log('Nothing matches; using Response.error()');
|
||||
return Response.error();
|
||||
}
|
||||
|
||||
/**
|
||||
* The behavior when there's a matching manifest for our client URL.
|
||||
*
|
||||
* @private
|
||||
* @param {FetchEvent} event
|
||||
* @param {String} manifestUrl
|
||||
* @param {String} clientUrl
|
||||
* @return {Promise.<Response>}
|
||||
*/
|
||||
function manifestBehavior(event, manifestUrl, clientUrl) {
|
||||
if (event.clientId) {
|
||||
return idbHelpers[constants.STORES.CLIENT_ID_TO_HASH].get(event.clientId)
|
||||
.then((hash) => {
|
||||
// If we already have a hash assigned to this client id, use that
|
||||
// manifest to implement the AppCache logic.
|
||||
if (hash) {
|
||||
return getParsedManifestVersion(manifestUrl, hash)
|
||||
.then((parsedManifest) => appCacheLogic(event, parsedManifest, hash,
|
||||
clientUrl));
|
||||
}
|
||||
|
||||
// If there's isn't yet a hash for this client id, then get the latest
|
||||
// version of the manifest, and use that to implement AppCache logic.
|
||||
// Also, establish the client id to hash mapping for future use.
|
||||
return getLatestManifestVersion(manifestUrl).then((latest) => {
|
||||
return saveClientIdAndHash(event.clientId, latest.hash)
|
||||
.then(() => appCacheLogic(event, latest.parsed, latest.hash,
|
||||
clientUrl));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// If there's no client id, then just use the latest version of the
|
||||
// manifest to implement AppCache logic.
|
||||
return getLatestManifestVersion(manifestUrl).then(
|
||||
(latest) => appCacheLogic(event, latest.parsed, latest.hash, clientUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* The behavior when there is no matching manifest for our client URL.
|
||||
*
|
||||
* @private
|
||||
* @param {FetchEvent} event
|
||||
* @return {Promise.<Response>}
|
||||
*/
|
||||
function noManifestBehavior(event) {
|
||||
// If we fall through to this point, then we don't have a known
|
||||
// manifest associated with the client making the request.
|
||||
// We now need to check to see if our request URL matches a prefix
|
||||
// from the FALLBACK section of *any* manifest in our origin. If
|
||||
// there are multiple matches, the longest prefix wins. If there are
|
||||
// multiple prefixes of the same length in different manifest, then
|
||||
// the one returned last from IDB wins. (This might not match
|
||||
// browser behavior.)
|
||||
// See https://www.w3.org/TR/2011/WD-html5-20110525/offline.html#concept-appcache-matches-fallback
|
||||
return idbHelpers[constants.STORES.MANIFEST_URL_TO_CONTENTS].getAllValues()
|
||||
.then((manifests) => {
|
||||
logHelper.log('All manifests:', manifests);
|
||||
// Use .map() to create an array of the longest matching prefix
|
||||
// for each manifest. If no prefixes match for a given manifest,
|
||||
// the value will be ''.
|
||||
const longestForEach = manifests.map((manifestVersions) => {
|
||||
// Use the latest version of a given manifest.
|
||||
const parsedManifest =
|
||||
manifestVersions[manifestVersions.length - 1].parsed;
|
||||
return longestMatchingPrefix(
|
||||
Object.keys(parsedManifest.fallback), event.request.url);
|
||||
});
|
||||
logHelper.log('longestForEach:', longestForEach);
|
||||
|
||||
// Next, find which of the longest matching prefixes from each
|
||||
// manifest is the longest overall. Return both the index of the
|
||||
// manifest in which that match appears and the prefix itself.
|
||||
const longest = longestForEach.reduce((soFar, current, i) => {
|
||||
if (current.length >= soFar.prefix.length) {
|
||||
return {prefix: current, index: i};
|
||||
}
|
||||
|
||||
return soFar;
|
||||
}, {prefix: '', index: 0});
|
||||
logHelper.log('longest:', longest);
|
||||
|
||||
// Now that we know the longest overall prefix, we'll use that
|
||||
// to lookup the fallback URL value in the winning manifest.
|
||||
const fallbackKey = longest.prefix;
|
||||
logHelper.log('fallbackKey:', fallbackKey);
|
||||
if (fallbackKey) {
|
||||
const winningManifest = manifests[longest.index];
|
||||
logHelper.log('winningManifest:', winningManifest);
|
||||
const winningManifestVersion =
|
||||
winningManifest[winningManifest.length - 1];
|
||||
logHelper.log('winningManifestVersion:', winningManifestVersion);
|
||||
const hash = winningManifestVersion.hash;
|
||||
const parsedManifest = winningManifestVersion.parsed;
|
||||
return fetchWithFallback(event.request,
|
||||
parsedManifest.fallback[fallbackKey], hash);
|
||||
}
|
||||
|
||||
// If nothing matches, then just fetch().
|
||||
logHelper.log('Nothing at all matches. Using fetch()');
|
||||
return fetch(event.request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An attempt to mimic AppCache behavior, using the primitives available to
|
||||
* a service worker.
|
||||
*
|
||||
* @private
|
||||
* @param {FetchEvent} event
|
||||
* @return {Promise.<Response>}
|
||||
*/
|
||||
function appCacheBehaviorForEvent(event) {
|
||||
const requestUrl = new URL(event.request.url);
|
||||
logHelper.log('Starting appCacheBehaviorForUrl for ' + requestUrl);
|
||||
|
||||
// If this is a request that, as per the AppCache spec, should be handled
|
||||
// via a direct fetch(), then do that and bail early.
|
||||
if (event.request.headers.get('X-Use-Fetch') === 'true') {
|
||||
logHelper.log('Using fetch() because X-Use-Fetch: true');
|
||||
return fetch(event.request);
|
||||
}
|
||||
|
||||
// Appcache rules only apply to GETs & same-scheme requests.
|
||||
if (event.request.method !== 'GET' ||
|
||||
requestUrl.protocol !== location.protocol) {
|
||||
logHelper.log(
|
||||
'Using fetch() because AppCache does not apply to this request.');
|
||||
return fetch(event.request);
|
||||
}
|
||||
|
||||
return getClientUrlForEvent(event).then((clientUrl) => {
|
||||
logHelper.log('clientUrl is', clientUrl);
|
||||
return idbHelpers[constants.STORES.PATH_TO_MANIFEST].get(clientUrl)
|
||||
.then((manifestUrl) => {
|
||||
logHelper.log('manifestUrl is', manifestUrl);
|
||||
|
||||
if (manifestUrl) {
|
||||
return manifestBehavior(event, manifestUrl, clientUrl);
|
||||
}
|
||||
|
||||
logHelper.log('No matching manifest for client found.');
|
||||
return noManifestBehavior(event);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of client ids that are still active, this:
|
||||
* 1. Gets a list of all the client ids in IndexedDB's CLIENT_ID_TO_HASH
|
||||
* 2. Filters them to remove the active ones
|
||||
* 3. Delete the inactive entries from IndexedDB's CLIENT_ID_TO_HASH
|
||||
* 4. For each inactive one, return the corresponding hash association.
|
||||
*
|
||||
* @private
|
||||
* @param {Array.<String>} idsOfActiveClients
|
||||
* @return {Promise.<Array.<String>>}
|
||||
*/
|
||||
function cleanupClientIdAndHash(idsOfActiveClients) {
|
||||
return idbHelpers[constants.STORES.CLIENT_ID_TO_HASH].getAllKeys()
|
||||
.then((allKnownIds) => {
|
||||
return allKnownIds.filter((id) => !idsOfActiveClients.includes(id));
|
||||
}).then((idsOfInactiveClients) => {
|
||||
return Promise.all(idsOfInactiveClients.map((id) => {
|
||||
const storeName = constants.STORES.CLIENT_ID_TO_HASH;
|
||||
return idbHelpers[storeName].get(id).then((hash) => {
|
||||
return idbHelpers[constants.STORES.CLIENT_ID_TO_HASH].delete(id)
|
||||
.then(() => hash);
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fulfills with an array of all the hash ids that correspond to outdated
|
||||
* manifest versions.
|
||||
*
|
||||
* @private
|
||||
* @return {Promise.<Array.<String>>}
|
||||
*/
|
||||
function getHashesOfOlderVersions() {
|
||||
return idbHelpers[constants.STORES.MANIFEST_URL_TO_CONTENTS].getAllValues()
|
||||
.then((manifests) => {
|
||||
return manifests.map((versions) => {
|
||||
// versions.slice(0, -1) will give all the versions other than the
|
||||
// last, or [] if there's aren't any older versions.
|
||||
return versions.slice(0, -1).map((version) => version.hash);
|
||||
}).reduce((prev, curr) => {
|
||||
// Flatten the array-of-arrays into an array.
|
||||
return prev.concat(curr);
|
||||
}, []);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the following:
|
||||
* 1. Gets a list of all client ids associated with this service worker.
|
||||
* 2. Calls cleanupClientIdAndHash() to remove the out of date client id
|
||||
* to hash associations.
|
||||
* 3. Calls getHashesOfOlderVersions() to get a list of all the hashes
|
||||
* that correspond to out-of-date manifest versions.
|
||||
* 4. If there's a match between an out of date hash and a hash that is no
|
||||
* longer being used by a client, then it deletes the corresponding cache.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function cleanupOldCaches() {
|
||||
self.clients.matchAll().then((clients) => {
|
||||
return clients.map((client) => client.id);
|
||||
}).then((idsOfActiveClients) => {
|
||||
return cleanupClientIdAndHash(idsOfActiveClients);
|
||||
}).then((hashesNotInUse) => {
|
||||
return getHashesOfOlderVersions().then((hashesOfOlderVersions) => {
|
||||
return hashesOfOlderVersions.filter((hashOfOlderVersion) => {
|
||||
return hashesNotInUse.includes(hashOfOlderVersion);
|
||||
});
|
||||
});
|
||||
}).then((idsToDelete) => {
|
||||
logHelper.log('deleting cache ids', idsToDelete);
|
||||
return Promise.all(idsToDelete.map((cacheId) => caches.delete(cacheId)));
|
||||
});
|
||||
|
||||
// TODO: Delete the entry in the array stored in MANIFEST_URL_TO_CONTENT.
|
||||
}
|
||||
|
||||
/**
|
||||
* `goog.appCacheBehavior.fetch` is the main entry point to the library
|
||||
* from within service worker code.
|
||||
*
|
||||
* The goal of the library is to provide equivalent behavior to AppCache
|
||||
* whenever possible. The one difference in how this library behaves compared to
|
||||
* a native AppCache implementation is that its client-side code will attempt to
|
||||
* fetch a fresh AppCache manifest once any cached version is older than 24
|
||||
* hours. This works around a
|
||||
* [major pitfall](http://alistapart.com/article/application-cache-is-a-douchebag#section6)
|
||||
* in the native AppCache implementation.
|
||||
*
|
||||
* **Important**
|
||||
* In addition to calling `goog.appCacheBehavior.fetch()` from within your
|
||||
* service worker, you *must* add the following to each HTML document that
|
||||
* contains an App Cache Manifest:
|
||||
*
|
||||
* ```html
|
||||
* <script src="path/to/client-runtime.js"
|
||||
* data-service-worker="service-worker.js">
|
||||
* </script>
|
||||
* ```
|
||||
*
|
||||
* (The `data-service-worker` attribute is optional. If provided, it will
|
||||
* automatically call
|
||||
* [`navigator.serviceWorker.register()`](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register)
|
||||
* for you.)
|
||||
*
|
||||
* Once you've added `<script src="path/to/client-runtime.js"></script>` to
|
||||
* your HTML pages, you can use `goog.appCacheBehavior.fetch` within your
|
||||
* service worker script to get a `Response` suitable for passing to
|
||||
* [`FetchEvent.respondWidth()`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith):
|
||||
*
|
||||
* ```js
|
||||
* // Import the library into the service worker global scope:
|
||||
* // https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts
|
||||
* importScripts('path/to/appcache-behavior-import.js');
|
||||
*
|
||||
* self.addEventListener('fetch', event => {
|
||||
* event.respondWith(goog.appCacheBehavior.fetch(event).catch(error => {
|
||||
* // Fallback behavior goes here, e.g. return fetch(event.request);
|
||||
* }));
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* `goog.appCacheBehavior.fetch()` can be selectively applied to only a subset
|
||||
* of requests, to aid in the migration off of App Cache and onto a more
|
||||
* robust service worker implementation:
|
||||
*
|
||||
* ```js
|
||||
* // Import the library into the service worker global scope:
|
||||
* // https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts
|
||||
* importScripts('path/to/appcache-behavior-import.js');
|
||||
*
|
||||
* self.addEventListener('fetch', event => {
|
||||
* if (event.request.url.match(/legacyRegex/)) {
|
||||
* event.respondWith(goog.appCacheBehavior.fetch(event));
|
||||
* } else {
|
||||
* event.respondWith(goog.appCacheBehavior.fetch(event));
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @alias goog.appCacheBehavior.fetch
|
||||
* @param {FetchEvent} event
|
||||
* @return {Promise.<Response>}
|
||||
*/
|
||||
function fetchBehavior(event) {
|
||||
logHelper.log('client id is', event.clientId);
|
||||
return appCacheBehaviorForEvent(event).then((response) => {
|
||||
// If this is a navigation, clean up unused caches that correspond to old
|
||||
// AppCache manifest versions which are no longer associated with an
|
||||
// active client. This will be done asynchronously, and won't block the
|
||||
// response from being returned to the onfetch handler.
|
||||
if (event.request.mode === 'navigate') {
|
||||
cleanupOldCaches();
|
||||
}
|
||||
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
export {fetchBehavior as fetch};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-appcache-behavior/src/client-runtime.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
/**
|
||||
* # sw-appcache-behavior
|
||||
*
|
||||
* A service worker implementation of the behavior defined in a page's App
|
||||
* Cache manifest.
|
||||
*
|
||||
* In your web page you need to add the client-runtime.js file:
|
||||
*
|
||||
* ```
|
||||
* <script src="../build/client-runtime.js"
|
||||
* data-service-worker="service-worker.js"></script>
|
||||
* ```
|
||||
*
|
||||
* Then in your servier worker you must import the appcache-behavior-import.js
|
||||
* file:
|
||||
*
|
||||
* ```
|
||||
* importScripts('../build/appcache-behavior-import.js');
|
||||
*
|
||||
* self.addEventListener('fetch', (event) => {
|
||||
* event.respondWith(goog.appCacheBehavior.fetch(event));
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @module sw-appcache-behavior
|
||||
*/
|
||||
|
||||
import constants from './lib/constants.js';
|
||||
import idb from 'idb';
|
||||
import md5 from 'blueimp-md5';
|
||||
import parseAppCacheManifest from 'parse-appcache-manifest';
|
||||
|
||||
const swScript = document.currentScript.dataset.serviceWorker;
|
||||
const manifestAttribute = document.documentElement.getAttribute('manifest');
|
||||
|
||||
if (manifestAttribute && 'serviceWorker' in navigator) {
|
||||
const manifestUrl = (new URL(manifestAttribute, location.href)).href;
|
||||
|
||||
openIdb().then(function(db) {
|
||||
return checkManifestVersion(db, manifestUrl).then(function(hash) {
|
||||
return updateManifestAssociationForCurrentPage(db, manifestUrl, hash);
|
||||
});
|
||||
}).then(function() {
|
||||
if (swScript) {
|
||||
return navigator.serviceWorker.register(swScript);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a connection to IndexedDB, using the idb library.
|
||||
*
|
||||
* @private
|
||||
* @return {Promise.<DB>}
|
||||
*/
|
||||
function openIdb() {
|
||||
// TODO: Use idb-helpers.js instead.
|
||||
return idb.open(constants.DB_NAME, constants.DB_VERSION, function(upgradeDB) {
|
||||
if (upgradeDB.oldVersion === 0) {
|
||||
Object.keys(constants.STORES).forEach(function(objectStore) {
|
||||
upgradeDB.createObjectStore(constants.STORES[objectStore]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the Responses for one or more URLs, using the Cache Storage API.
|
||||
*
|
||||
* @private
|
||||
* @param {String} hash
|
||||
* @param {Array.<String>} urls
|
||||
* @return {Promise.<T>}
|
||||
*/
|
||||
function addToCache(hash, urls) {
|
||||
// Use the manifest hash as the name of the Cache to open.
|
||||
return caches.open(hash).then(function(cache) {
|
||||
const fetchRequests = urls.map(function(url) {
|
||||
// See Item 18.3 of https://html.spec.whatwg.org/multipage/browsers.html#downloading-or-updating-an-application-cache
|
||||
const request = new Request(url, {
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'X-Use-Fetch': true,
|
||||
},
|
||||
redirect: 'manual',
|
||||
});
|
||||
|
||||
return fetch(request).then(function(response) {
|
||||
const cacheControl = response.headers.get('Cache-Control');
|
||||
if (cacheControl && cacheControl.indexOf('no-store') !== -1) {
|
||||
// Bail early if we're told not to cache this response.
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.ok) {
|
||||
return cache.put(url, response);
|
||||
}
|
||||
|
||||
// See Item 18.5 of https://html.spec.whatwg.org/multipage/browsers.html#downloading-or-updating-an-application-cache
|
||||
if (response.status !== 404 &&
|
||||
response.status !== 410) {
|
||||
// Assuming this isn't a 200, 404 or 410, we want the .catch() to
|
||||
// trigger, which will cause any previously cached Response for this
|
||||
// URL to be copied over to this new cache.
|
||||
return Promise.reject();
|
||||
}
|
||||
}).catch(function() {
|
||||
// We're here if one of the following happens:
|
||||
// - The fetch() rejected due to a NetworkError.
|
||||
// - The HTTP status code from the fetch() was something other than
|
||||
// 200, 404, and 410 AND the response isn't Cache-Control: no-store
|
||||
return caches.match(url).then(function(response) {
|
||||
// Add a copy of the cached response to this new cache, if it exists.
|
||||
if (response) {
|
||||
return cache.put(url, response.clone());
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(fetchRequests);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the copy of a manifest obtained from fetch() with the copy stored
|
||||
* in IndexedDB. If they differ, it kicks off the manifest update process.
|
||||
*
|
||||
* It returns a Promise which fulfills with the hash for the current manifest.
|
||||
*
|
||||
* @private
|
||||
* @param {DB} db
|
||||
* @param {String} manifestUrl
|
||||
* @return {Promise.<String>}
|
||||
*/
|
||||
function checkManifestVersion(db, manifestUrl) {
|
||||
const tx = db.transaction(constants.STORES.MANIFEST_URL_TO_CONTENTS);
|
||||
const store = tx.objectStore(
|
||||
constants.STORES.MANIFEST_URL_TO_CONTENTS);
|
||||
|
||||
// See Item 4 of https://html.spec.whatwg.org/multipage/browsers.html#downloading-or-updating-an-application-cache
|
||||
const manifestRequest = new Request(manifestUrl, {
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'X-Use-Fetch': true,
|
||||
},
|
||||
});
|
||||
|
||||
return Promise.all([
|
||||
// TODO: Handle manifest fetch failure errors.
|
||||
fetch(manifestRequest).then(function(manifestResponse) {
|
||||
const dateHeaderValue = manifestResponse.headers.get('date');
|
||||
if (dateHeaderValue) {
|
||||
const manifestDate = new Date(dateHeaderValue).valueOf();
|
||||
// Calculate the age of the manifest in milliseconds.
|
||||
const manifestAgeInMillis = Date.now() - manifestDate;
|
||||
// If the age is greater than 24 hours, then we need to refetch without
|
||||
// hitting the cache.
|
||||
if (manifestAgeInMillis > (24 * 60 * 60 * 1000)) {
|
||||
const noCacheRequest = new Request(manifestUrl, {
|
||||
credentials: 'include',
|
||||
// See https://fetch.spec.whatwg.org/#requestcache
|
||||
cache: 'reload',
|
||||
headers: {
|
||||
'X-Use-Fetch': true,
|
||||
},
|
||||
});
|
||||
|
||||
return fetch(noCacheRequest).then(function(noCacheResponse) {
|
||||
return noCacheResponse.text();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return manifestResponse.text();
|
||||
}).then(function(text) {
|
||||
return {
|
||||
// Hash a combination of URL and text so that two identical manifests
|
||||
// served from a different location are treated distinctly.
|
||||
hash: md5(manifestUrl + text),
|
||||
text: text,
|
||||
};
|
||||
}),
|
||||
store.get(manifestUrl),
|
||||
]).then(function(values) {
|
||||
// values[0].hash is the MD5 hash of the manifest returned by fetch().
|
||||
// values[0].text is the manifest text returned by fetch().
|
||||
// values[1] is array of Objects with {hash, parsed} properties, or null.
|
||||
const knownManifests = values[1] || [];
|
||||
const knownManifestVersion = knownManifests.some(function(entry) {
|
||||
return entry.hash === values[0].hash;
|
||||
});
|
||||
|
||||
if (knownManifestVersion) {
|
||||
// If we already know about this manifest version, return the hash.
|
||||
return values[0].hash;
|
||||
}
|
||||
|
||||
// If the hash of the manifest retrieved from the network isn't already
|
||||
// in the list of known manifest hashes, then trigger an update.
|
||||
return performManifestUpdate(db, manifestUrl, values[0].hash,
|
||||
values[0].text, knownManifests);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the newest manifest text into the format described at
|
||||
* https://www.npmjs.com/package/parse-appcache-manifest
|
||||
* The parsed manifest is stored in IndexedDB.
|
||||
* This also calls addToCache() to cache the relevant URLs from the manifest.
|
||||
*
|
||||
* It returns a Promise which fulfills with the hash for the current manifest.
|
||||
*
|
||||
* @private
|
||||
* @param {DB} db
|
||||
* @param {String} manifestUrl
|
||||
* @param {String} hash
|
||||
* @param {String} text
|
||||
* @param {Array.<Object>} knownManifests
|
||||
* @return {Promise.<String>}
|
||||
*/
|
||||
function performManifestUpdate(db, manifestUrl, hash, text, knownManifests) {
|
||||
const parsedManifest = makeManifestUrlsAbsolute(manifestUrl,
|
||||
parseAppCacheManifest(text));
|
||||
|
||||
knownManifests.push({
|
||||
hash: hash,
|
||||
parsed: parsedManifest,
|
||||
});
|
||||
|
||||
const fallbackUrls = Object.keys(parsedManifest.fallback).map(function(key) {
|
||||
return parsedManifest.fallback[key];
|
||||
});
|
||||
|
||||
const urlsToCache = parsedManifest.cache.concat(fallbackUrls);
|
||||
|
||||
// All the master entries, i.e. those pages that were associated with an older
|
||||
// version of the manifest at the same URL, should be copied over to the new
|
||||
// cache as well.
|
||||
const readTx = db.transaction(constants.STORES.PATH_TO_MANIFEST, 'readonly');
|
||||
readTx.objectStore(constants.STORES.PATH_TO_MANIFEST).iterateCursor(
|
||||
function(cursor) {
|
||||
if (cursor) {
|
||||
if (cursor.value === manifestUrl) {
|
||||
urlsToCache.push(cursor.key);
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return readTx.complete.then(function() {
|
||||
const writeTx = db.transaction(constants.STORES.MANIFEST_URL_TO_CONTENTS,
|
||||
'readwrite');
|
||||
const manifestUrlToContentsStore = writeTx.objectStore(
|
||||
constants.STORES.MANIFEST_URL_TO_CONTENTS);
|
||||
|
||||
return Promise.all([
|
||||
manifestUrlToContentsStore.put(knownManifests, manifestUrl),
|
||||
// Wait on tx.complete to ensure that the transaction succeeded.
|
||||
writeTx.complete,
|
||||
addToCache(hash, urlsToCache),
|
||||
]);
|
||||
}).then(function() {
|
||||
return hash;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates IndexedDB to indicate that the current page's URL is associated
|
||||
* with the AppCache manifest at manifestUrl.
|
||||
* It also adds the current page to the cache versioned with hash, matching
|
||||
* the master entry cache-as-you-go behavior you get with AppCache.
|
||||
*
|
||||
* @private
|
||||
* @param {DB} db
|
||||
* @param {String} manifestUrl
|
||||
* @param {String} hash
|
||||
* @return {Promise.<T>}
|
||||
*/
|
||||
function updateManifestAssociationForCurrentPage(db, manifestUrl, hash) {
|
||||
const tx = db.transaction(constants.STORES.PATH_TO_MANIFEST,
|
||||
'readwrite');
|
||||
const store = tx.objectStore(constants.STORES.PATH_TO_MANIFEST);
|
||||
|
||||
return Promise.all([
|
||||
store.put(manifestUrl, location.href),
|
||||
// Wait on tx.complete to ensure that the transaction succeeded.
|
||||
tx.complete,
|
||||
addToCache(hash, [location.href]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all the URLs in a given manifest's CACHE, NETWORK, and FALLBACK
|
||||
* sections to be absolute URLs.
|
||||
*
|
||||
* @private
|
||||
* @param {String} baseUrl
|
||||
* @param {Object} originalManifest
|
||||
* @return {Object}
|
||||
*/
|
||||
function makeManifestUrlsAbsolute(baseUrl, originalManifest) {
|
||||
const manifest = {};
|
||||
|
||||
manifest.cache = originalManifest.cache.map(function(relativeUrl) {
|
||||
return (new URL(relativeUrl, baseUrl)).href;
|
||||
});
|
||||
|
||||
manifest.network = originalManifest.network.map(function(relativeUrl) {
|
||||
if (relativeUrl === '*') {
|
||||
return relativeUrl;
|
||||
}
|
||||
|
||||
return (new URL(relativeUrl, baseUrl)).href;
|
||||
});
|
||||
|
||||
manifest.fallback = {};
|
||||
Object.keys(originalManifest.fallback).forEach(function(key) {
|
||||
manifest.fallback[(new URL(key, baseUrl)).href] =
|
||||
(new URL(originalManifest.fallback[key], baseUrl)).href;
|
||||
});
|
||||
|
||||
return manifest;
|
||||
}
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-background-sync-queue/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-background-sync-queue
|
||||
*
|
||||
* Queues failed requests and uses the Background Sync API to replay those
|
||||
* requests at a later time when the network state has changed.
|
||||
*
|
||||
* @module sw-background-sync-queue
|
||||
*/
|
||||
import {getResponse} from './lib/response-manager';
|
||||
import {setDbName} from './lib/background-sync-idb-helper';
|
||||
import BackgroundSyncQueue from './lib/background-sync-queue';
|
||||
import {cleanupQueue} from './lib/queue-utils';
|
||||
import assert from '../../../lib/assert';
|
||||
|
||||
/**
|
||||
* In order to use this library call `goog.backgroundSyncQueue.initialize()`.
|
||||
* It will take care of setting up IndexedDB for storing requests and broadcast
|
||||
* channel for communication of request creations. Also this attaches a handler
|
||||
* to `sync` event and replays the queued requeusts.
|
||||
*
|
||||
* @alias goog.backgroundSyncQueue.initialize
|
||||
*
|
||||
* @param {Object} [input] The input object to this function
|
||||
* @param {string} [input.dbName] The name of the db to store requests and
|
||||
* responses
|
||||
*/
|
||||
async function initialize({dbName} = {}) {
|
||||
if(dbName) {
|
||||
assert.isType({dbName}, 'string');
|
||||
setDbName(dbName);
|
||||
}
|
||||
await cleanupQueue();
|
||||
}
|
||||
|
||||
export {
|
||||
initialize,
|
||||
getResponse,
|
||||
BackgroundSyncQueue,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-background-sync-queue/src/lib/background-sync-queue.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import RequestManager from './request-manager';
|
||||
import RequestQueue from './request-queue';
|
||||
import {maxAge} from './constants';
|
||||
import assert from '../../../../lib/assert';
|
||||
import IDBHelper from '../../../../lib/idb-helper';
|
||||
import {getDbName} from './background-sync-idb-helper';
|
||||
|
||||
/**
|
||||
* Use the instance of this class to push the failed requests into the queue.
|
||||
*
|
||||
* @example
|
||||
* // Case 1: When you want to push the requests manually
|
||||
* let bgQueue = new goog.backgroundSyncQueue.BackgroundSyncQueue();
|
||||
* self.addEventListener('fetch', function(e) {
|
||||
* if (e.request.url.startsWith('https://jsonplaceholder.typicode.com')) {
|
||||
* const clone = e.request.clone();
|
||||
* e.respondWith(fetch(e.request).catch((err)=>{
|
||||
* bgQueue.pushIntoQueue({
|
||||
* request: clone,
|
||||
* });
|
||||
* throw err;
|
||||
* }));
|
||||
* }
|
||||
* });
|
||||
* // Case 2: When you want the higher level framework to take care of failed
|
||||
* // requests
|
||||
* let bgQueue = new goog.backgroundSyncQueue.BackgroundSyncQueue({callbacks:
|
||||
* {
|
||||
* onResponse: async(hash, res) => {
|
||||
* self.registration.showNotification('Background sync demo', {
|
||||
* body: 'Product has been purchased.',
|
||||
* icon: 'https://shop.polymer-project.org/images/shop-icon-384.png',
|
||||
* });
|
||||
* },
|
||||
* onRetryFailure: (hash) => {},
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
* plugins: [bgQueue],
|
||||
* });
|
||||
*
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: new RegExp('^https://jsonplaceholder.typicode.com'),
|
||||
* handler: new goog.runtimeCaching.NetworkOnly({requestWrapper}),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @alias goog.backgroundSyncQueue.BackgroundSyncQueue
|
||||
* @class BackgroundSyncQueue
|
||||
*
|
||||
*/
|
||||
class BackgroundSyncQueue {
|
||||
/**
|
||||
* Creates an instance of BackgroundSyncQueue with the given options
|
||||
*
|
||||
* @param {Object} [input]
|
||||
* @param {Number} [input.maxRetentionTime = 5 days] Time for which a queued
|
||||
* request will live in the queue(irespective of failed/success of replay).
|
||||
* @param {Object} [input.callbacks] Callbacks for successfull/ failed
|
||||
* replay of a request.
|
||||
* @param {string} [input.queueName] Queue name inside db in which
|
||||
* requests will be queued.
|
||||
* @param {BroadcastChannel=} [input.broadcastChannel] BroadcastChannel
|
||||
* which will be used to publish messages when the request will be queued.
|
||||
*/
|
||||
constructor({maxRetentionTime = maxAge, callbacks, queueName,
|
||||
broadcastChannel} = {}) {
|
||||
if(queueName) {
|
||||
assert.isType({queueName}, 'string');
|
||||
}
|
||||
|
||||
if(maxRetentionTime) {
|
||||
assert.isType({maxRetentionTime}, 'number');
|
||||
}
|
||||
|
||||
if(broadcastChannel) {
|
||||
assert.isInstance({broadcastChannel}, BroadcastChannel);
|
||||
}
|
||||
|
||||
this._queue = new RequestQueue({
|
||||
config: {
|
||||
maxAge: maxRetentionTime,
|
||||
},
|
||||
queueName,
|
||||
idbQDb: new IDBHelper(getDbName(), 1, 'QueueStore'),
|
||||
broadcastChannel,
|
||||
});
|
||||
this._requestManager = new RequestManager({callbacks,
|
||||
queue: this._queue});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function pushes a given request into the IndexedDb Queue
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Request} input.request The request which is to be queued
|
||||
*
|
||||
* @return {Promise} Promise which resolves when the request is pushed in
|
||||
* the queue.
|
||||
*/
|
||||
pushIntoQueue({request}) {
|
||||
assert.isInstance({request}, Request);
|
||||
return this._queue.push({request});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps `pushIntoQueue` in a callback used by higher level framework.
|
||||
* This function pushes a given request into the IndexedDb Queue.
|
||||
* NOTE: If you are writting the fetch handler for background sync manually,
|
||||
* please ignore this.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Request} input.request The request which is to be queued
|
||||
*
|
||||
* @return {Promise} Promise which resolves when the request is pushed in
|
||||
* the queue.
|
||||
*/
|
||||
fetchDidFail({request}) {
|
||||
return this.pushIntoQueue({request});
|
||||
}
|
||||
}
|
||||
|
||||
export default BackgroundSyncQueue;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-background-sync-queue/src/lib/response-manager.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import {getDbName} from './background-sync-idb-helper';
|
||||
import IDBHelper from '../../../../lib/idb-helper';
|
||||
|
||||
/**
|
||||
* Puts the fetched response in the IDB
|
||||
*
|
||||
* @param {Object} config
|
||||
* @private
|
||||
*/
|
||||
async function putResponse({hash, idbObject, response, idbQDb}) {
|
||||
const _idbQHelper = idbQDb;
|
||||
idbObject.response = {
|
||||
headers: JSON.stringify([...response.headers]),
|
||||
status: response.status,
|
||||
body: await response.blob(),
|
||||
};
|
||||
_idbQHelper.put(hash, idbObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the fetched response for the given id of the request
|
||||
*
|
||||
* @alias goog.backgroundSyncQueue.getResponse
|
||||
*
|
||||
* @param {String} id The ID of the request given back by the broaadcast
|
||||
* channel
|
||||
* @return {Object} response Fetched response of the request.
|
||||
*/
|
||||
async function getResponse({id}) {
|
||||
const _idbQHelper = new IDBHelper(getDbName(), 1, 'QueueStore');
|
||||
const object = await _idbQHelper.get(id);
|
||||
if (object && object.response) {
|
||||
return object.response;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
putResponse,
|
||||
getResponse,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-broadcast-cache-update/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-broadcast-cache-update
|
||||
*
|
||||
* A helper library that uses the Broadcast Channel API to announce when
|
||||
* two Response objects differ.
|
||||
*
|
||||
* The main use of this module will be instantiating a new
|
||||
* `BroadcastCacheUpdatePlugin` and passing it to a
|
||||
* {@link module:sw-runtime-caching.RequestWrapper|RequestWrapper},
|
||||
* as shown in the first example below.
|
||||
*
|
||||
* You can listen for updates from your web app by adding an event listener on
|
||||
* a `BroadcastChannel` within a page, using the same channel name as
|
||||
* what's used within the service worker, as shown in the second example below.
|
||||
*
|
||||
* @example <caption>Using the BroadcastCacheUpdatePlugin class in a
|
||||
* service worker.</caption>
|
||||
*
|
||||
* const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
* cacheName: 'text-files',
|
||||
* plugins: [
|
||||
* new goog.broadcastCacheUpdate.BroadcastCacheUpdatePlugin(
|
||||
* {channelName: 'cache-updates'})
|
||||
* ],
|
||||
* });
|
||||
*
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: /\.txt$/,
|
||||
* handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper}),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @example <caption>Listening for the broadcast message in the
|
||||
* window.</caption>
|
||||
*
|
||||
* const updateChannel = new BroadcastChannel('cache-updates');
|
||||
* updateChannel.addEventListener('message', event => {
|
||||
* console.log(`Cache updated: ${event.data.payload.updatedUrl}`);
|
||||
* });
|
||||
*
|
||||
* @module sw-broadcast-cache-update
|
||||
*/
|
||||
|
||||
import BroadcastCacheUpdate from './lib/broadcast-cache-update';
|
||||
import BroadcastCacheUpdatePlugin from './lib/broadcast-cache-update-plugin';
|
||||
import broadcastUpdate from './lib/broadcast-update';
|
||||
import {cacheUpdatedMessageType} from './lib/constants';
|
||||
import responsesAreSame from './lib/responses-are-same';
|
||||
|
||||
export {
|
||||
BroadcastCacheUpdate,
|
||||
BroadcastCacheUpdatePlugin,
|
||||
broadcastUpdate,
|
||||
cacheUpdatedMessageType,
|
||||
responsesAreSame,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-broadcast-cache-update/src/lib/broadcast-cache-update-plugin.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import BroadcastCacheUpdate from './broadcast-cache-update';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* Can be used to compare two [Responses](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
||||
* and uses the {@link https://developers.google.com/web/updates/2016/09/broadcastchannel|Broadcast Channel API}
|
||||
* to notify interested parties when those responses differ.
|
||||
*
|
||||
* For efficiency's sake, the underlying response bodies are not compared;
|
||||
* only specific response headers are checked.
|
||||
*
|
||||
* This class is meant to be automatically invoked as a plugin to a
|
||||
* {@link module:sw-runtime-caching.RequestWrapper|RequestWrapper}, which is
|
||||
* used by the `sw-lib` and `sw-runtime-caching` modules.
|
||||
*
|
||||
* If you would like to use this functionality outside of the `RequestWrapper`
|
||||
* context, please use the `BroadcastCacheUpdate` class directly.
|
||||
*
|
||||
* @example <caption>Added as a "plugin" to a `RequestWrapper` to
|
||||
* automatically dispatch messages on a cache update</caption>
|
||||
*
|
||||
* const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
* cacheName: 'runtime-cache',
|
||||
* plugins: [
|
||||
* new goog.broadcastCacheUpdate.Plugin({channelName: 'cache-updates'})
|
||||
* ]
|
||||
* });
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* match: ({url}) => url.domain === 'example.com',
|
||||
* handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper})
|
||||
* });
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*/
|
||||
class BroadcastCacheUpdatePlugin extends BroadcastCacheUpdate {
|
||||
/**
|
||||
* A "lifecycle" callback that will be triggered automatically by the
|
||||
* `sw-lib` and `sw-runtime-caching` handlers when an entry is added to a
|
||||
* cache.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input The input object to this function.
|
||||
* @param {string} input.cacheName Name of the cache the responses belong to.
|
||||
* @param {Response} [input.oldResponse] The previous cached value, if any.
|
||||
* @param {Response} input.newResponse The new value in the cache.
|
||||
*/
|
||||
cacheDidUpdate({cacheName, oldResponse, newResponse}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
assert.isInstance({newResponse}, Response);
|
||||
|
||||
if (oldResponse) {
|
||||
this.notifyIfUpdated({
|
||||
cacheName,
|
||||
first: oldResponse,
|
||||
second: newResponse,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BroadcastCacheUpdatePlugin;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-broadcast-cache-update/src/lib/broadcast-cache-update.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import ErrorFactory from './error-factory';
|
||||
import assert from '../../../../lib/assert';
|
||||
import broadcastUpdate from './broadcast-update';
|
||||
import responsesAreSame from './responses-are-same';
|
||||
import {defaultHeadersToCheck, defaultSource} from './constants';
|
||||
|
||||
/**
|
||||
* Can be used to compare two [Responses](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
||||
* and uses the {@link https://developers.google.com/web/updates/2016/09/broadcastchannel|Broadcast Channel API}
|
||||
* to notify interested parties when those responses differ.
|
||||
*
|
||||
* For efficiency's sake, the underlying response bodies are not compared;
|
||||
* only specific response headers are checked.
|
||||
*
|
||||
* This class can be used inside any service worker, without having to use any
|
||||
* of the other modules in this repo.
|
||||
*
|
||||
* If you'd like to use this functionality but are already using `sw-lib` or
|
||||
* `sw-runtime-caching`, then please see the corresponding plugin,
|
||||
* `BroadcastCacheUpdatePlugin`, for a easy integration.
|
||||
*
|
||||
* @example <caption>Using BroadcastCacheUpdate when you're handling your
|
||||
* own fetch and request logic.</caption>
|
||||
*
|
||||
* const url = '/path/to/file';
|
||||
* const cacheName = 'my-runtime-cache';
|
||||
* const bcu = new goog.broadcastCacheUpdate.BroadcastCacheUpdate(
|
||||
* {channelName: 'cache-updates'});
|
||||
*
|
||||
* Promise.all([
|
||||
* caches.open(cacheName).then((cache) => cache.match(url)),
|
||||
* fetch(url),
|
||||
* ]).then(([first, second]) => {
|
||||
* if (first) {
|
||||
* bcu.notifyIfUpdated({cacheName, first, second});
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*/
|
||||
class BroadcastCacheUpdate {
|
||||
/**
|
||||
* Dispatches cache update messages when a cached response has been updated.
|
||||
* Messages will be dispatched on a broadcast channel with the name provided
|
||||
* as channelName parameter in the constructor.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {string} input.channelName The name that will be used when creating
|
||||
* the `BroadcastChannel`.
|
||||
* @param {Array<string>} input.headersToCheck A list of headers that will be
|
||||
* used to determine whether the responses differ. Defaults to
|
||||
* `['content-length', 'etag', 'last-modified']`.
|
||||
* @param {string} input.source An attribution value that indicates where
|
||||
* the update originated. Defaults to 'sw-broadcast-cache-update'.
|
||||
*/
|
||||
constructor({channelName, headersToCheck, source}={}) {
|
||||
if (typeof channelName !== 'string' || channelName.length === 0) {
|
||||
throw ErrorFactory.createError('channel-name-required');
|
||||
}
|
||||
|
||||
this.channelName = channelName;
|
||||
this.headersToCheck = headersToCheck || defaultHeadersToCheck;
|
||||
this.source = source || defaultSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {BroadcastChannel} The underlying
|
||||
* [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel/BroadcastChannel)
|
||||
* instance used for broadcasting updates.
|
||||
*/
|
||||
get channel() {
|
||||
if (!this._channel) {
|
||||
this._channel = new BroadcastChannel(this.channelName);
|
||||
}
|
||||
return this._channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* An explicit method to call from your own code to trigger the comparison of
|
||||
* two [Responses](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
||||
* and fire off a notification via the
|
||||
* {@link https://developers.google.com/web/updates/2016/09/broadcastchannel|Broadcast Channel API}
|
||||
* if they differ.
|
||||
*
|
||||
* @param {Object} input The input object to this function.
|
||||
* @param {Response} input.first One of the responses to compare.
|
||||
* This should not be an {@link http://stackoverflow.com/questions/39109789|opaque response}.
|
||||
* @param {Response} input.second Another of the respones to compare.
|
||||
* This should not be an {@link http://stackoverflow.com/questions/39109789|opaque response}.
|
||||
* @param {string} input.cacheName Name of the cache the responses belong to.
|
||||
*/
|
||||
notifyIfUpdated({first, second, cacheName}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
|
||||
if (
|
||||
!responsesAreSame({first, second, headersToCheck: this.headersToCheck})) {
|
||||
broadcastUpdate({cacheName, url: second.url,
|
||||
channel: this.channel, source: this.source});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BroadcastCacheUpdate;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-broadcast-cache-update/src/lib/broadcast-update.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import assert from '../../../../lib/assert';
|
||||
import {cacheUpdatedMessageType} from './constants';
|
||||
|
||||
/**
|
||||
* You would not normally call this method directly; it's called automatically
|
||||
* by an instance of the {@link BroadcastCacheUpdate} class. It's exposed here
|
||||
* for the benefit of developers who would rather not use the full
|
||||
* `BroadcastCacheUpdate` implementation.
|
||||
*
|
||||
* Calling this will dispatch a message on the provided {@link https://developers.google.com/web/updates/2016/09/broadcastchannel|Broadcast Channel}
|
||||
* to notify interested subscribers about a change to a cached resource.
|
||||
*
|
||||
* The message that's posted has a formation inspired by the
|
||||
* [Flux standard action](https://github.com/acdlite/flux-standard-action#introduction)
|
||||
* format like so:
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* type: 'CACHE_UPDATED',
|
||||
* meta: 'sw-broadcast-cache-update',
|
||||
* payload: {
|
||||
* cacheName: 'the-cache-name',
|
||||
* updatedUrl: 'https://example.com/'
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* (Usage of [Flux](https://facebook.github.io/flux/) itself is not at
|
||||
* all required.)
|
||||
*
|
||||
* @example
|
||||
* goog.broadcastCacheUpdate.broadcastUpdate({
|
||||
* channel: new BroadcastChannel('Channel Name'),
|
||||
* cacheName: 'example-cache-name',
|
||||
* url: '/',
|
||||
* source: 'custom-library'
|
||||
* });
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {BroadcastChannel} input.channel The `BroadcastChannel` to use.
|
||||
* @param {string} input.cacheName The name of the cache in which the updated
|
||||
* `Response` was stored.
|
||||
* @param {string} input.url The URL associated with the updated `Response`.
|
||||
* @param {string} input.source A string identifying this library as the source
|
||||
* of the update message.
|
||||
*/
|
||||
function broadcastUpdate({channel, cacheName, url, source}) {
|
||||
assert.isInstance({channel}, BroadcastChannel);
|
||||
assert.isType({cacheName}, 'string');
|
||||
assert.isType({source}, 'string');
|
||||
assert.isType({url}, 'string');
|
||||
|
||||
channel.postMessage({
|
||||
type: cacheUpdatedMessageType,
|
||||
meta: source,
|
||||
payload: {
|
||||
cacheName: cacheName,
|
||||
updatedUrl: url,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default broadcastUpdate;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-broadcast-cache-update/src/lib/constants.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The value `'CACHE_UPDATED'`, used as the `type` field of the update message.
|
||||
*
|
||||
* @type {string}
|
||||
*
|
||||
* @example
|
||||
* // Prints 'CACHE_UPDATED'
|
||||
* console.log(goog.broadcastCacheUpdate.cacheUpdatedMessageType);
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*/
|
||||
const cacheUpdatedMessageType = 'CACHE_UPDATED';
|
||||
|
||||
/**
|
||||
* The default headers to compare when determining whether two `Response`
|
||||
* objects are different.
|
||||
*
|
||||
* @private
|
||||
* @type {Array<string>}
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*/
|
||||
const defaultHeadersToCheck = [
|
||||
'content-length',
|
||||
'etag',
|
||||
'last-modified',
|
||||
];
|
||||
|
||||
/**
|
||||
* The value `'sw-broadcast-cache-update'`, used as the `meta` field of the
|
||||
* update message.
|
||||
*
|
||||
* @private
|
||||
* @type {string}
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*/
|
||||
const defaultSource = 'sw-broadcast-cache-update';
|
||||
|
||||
export {
|
||||
cacheUpdatedMessageType,
|
||||
defaultHeadersToCheck,
|
||||
defaultSource,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-broadcast-cache-update/src/lib/responses-are-same.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import ErrorFactory from './error-factory';
|
||||
|
||||
/**
|
||||
* Given two `Response`s, compares several header values to see if they are
|
||||
* the same or not.
|
||||
*
|
||||
* @example
|
||||
* const responseIsSame = responsesAreSame({
|
||||
* first: firstResponse,
|
||||
* second: secondResponse,
|
||||
* headersToCheck: [
|
||||
* 'content-length',
|
||||
* 'etag',
|
||||
* 'last-modified',
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* @memberof module:sw-broadcast-cache-update
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Response} input.first One of the `Response`s.
|
||||
* @param {Response} input.second Another of the `Response`s.
|
||||
* @param {Array<string>} input.headersToCheck A list of headers that will be
|
||||
* used to determine whether the `Response`s differ.
|
||||
* @return {boolean} Whether or not the `Response` objects are assumed to be
|
||||
* the same.
|
||||
*/
|
||||
function responsesAreSame({first, second, headersToCheck}={}) {
|
||||
if (!(first instanceof Response &&
|
||||
second instanceof Response &&
|
||||
headersToCheck instanceof Array)) {
|
||||
throw ErrorFactory.createError('responses-are-same-parameters-required');
|
||||
}
|
||||
|
||||
return headersToCheck.every((header) => {
|
||||
return (first.headers.has(header) === second.headers.has(header)) &&
|
||||
(first.headers.get(header) === second.headers.get(header));
|
||||
});
|
||||
}
|
||||
|
||||
export default responsesAreSame;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-build/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>// This will be the logic that powers both module and CLI
|
||||
const generateSW = require('./lib/generate-sw');
|
||||
const getFileManifestEntries = require('./lib/get-file-manifest-entries');
|
||||
const generateFileManifest = require('./lib/generate-file-manifest');
|
||||
|
||||
/**
|
||||
* # sw-build
|
||||
*
|
||||
* To get a list of url's and a corresponding revision details, call either
|
||||
* `generateFileManifest` or `getFileManifestEntries()`.
|
||||
*
|
||||
* `generateFileManifest()` will run globs over a directory of static assets
|
||||
* and write a JavaScript file containing URL's and revision details for those
|
||||
* files.
|
||||
*
|
||||
* If you'd rather receive the data as a JavaScript Array, use
|
||||
* `getFileManifestEntries()` instead.
|
||||
*
|
||||
* If you only need precaching of your static assets in your service
|
||||
* worker and nothing else, you can generate complete service worker
|
||||
* with `generateSW()`.
|
||||
*
|
||||
* @example <caption>Generate a build manifest file.</caption>
|
||||
* const swBuild = require('sw-build');
|
||||
*
|
||||
* swBuild.generateFileManifest({
|
||||
* rootDirectory: './build/',
|
||||
* dest: './build/scripts/manifest.js',
|
||||
* globPatterns: ['**\/*.{html,js,css}'],
|
||||
* globIgnores: ['admin.html'],
|
||||
* templatedUrls: {
|
||||
* '/shell': ['shell.hbs', 'main.css', 'shell.css'],
|
||||
* },
|
||||
* })
|
||||
* .then(() => {
|
||||
* console.log('Build file has been created.');
|
||||
* });
|
||||
*
|
||||
* @example <caption>Get a list of files with revision details.</caption>
|
||||
* const swBuild = require('sw-build');
|
||||
*
|
||||
* swBuild.getFileManifestEntries({
|
||||
* rootDirectory: './build/',
|
||||
* globPatterns: ['**\/*.{html,js,css}'],
|
||||
* globIgnores: ['admin.html'],
|
||||
* templatedUrls: {
|
||||
* '/shell': ['shell.hbs', 'main.css', 'shell.css'],
|
||||
* },
|
||||
* })
|
||||
* .then((fileDetails) => {
|
||||
* // An array of file details include a `url` and `revision` parameter.
|
||||
* });
|
||||
*
|
||||
* @example <caption>Generate a service worker for a project.</caption>
|
||||
* const swBuild = require('sw-build');
|
||||
*
|
||||
* swBuild.generateSW({
|
||||
* rootDirectory: './build/',
|
||||
* dest: './build/sw.js',
|
||||
* globPatterns: ['**\/*.{html,js,css}'],
|
||||
* globIgnores: ['admin.html'],
|
||||
* templatedUrls: {
|
||||
* '/shell': ['shell.hbs', 'main.css', 'shell.css'],
|
||||
* },
|
||||
* })
|
||||
* .then(() => {
|
||||
* console.log('Service worker generated.');
|
||||
* });
|
||||
*
|
||||
* @module sw-build
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
generateSW,
|
||||
generateFileManifest,
|
||||
getFileManifestEntries,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-build/src/lib/generate-file-manifest.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const getFileManifestEntries = require('./get-file-manifest-entries');
|
||||
const writeFileManifest = require('./utils/write-file-manifest');
|
||||
const errors = require('./errors');
|
||||
|
||||
/**
|
||||
* @example <caption>Generate a build manifest of static assets, which could
|
||||
* then be used with a service worker.</caption>
|
||||
* const swBuild = require('sw-build');
|
||||
*
|
||||
* swBuild.generateFileManifest({
|
||||
* dest: './build/manifest.js'
|
||||
* rootDirectory: './build/',
|
||||
* globPatterns: ['**\/*.{html,js,css}'],
|
||||
* globIgnores: ['admin.html'],
|
||||
* format: 'iife', // alternatively, use 'es'
|
||||
* })
|
||||
* .then(() => {
|
||||
* console.log('Build Manifest generated.');
|
||||
* });
|
||||
*
|
||||
* This method will generate a file manifest that can be used in a service
|
||||
* worker for caching assets offline.
|
||||
* @param {Object} input
|
||||
* @param {String} input.dest The name and path you wish to write your
|
||||
* manifest file to.
|
||||
* @param {String} input.rootDirectory The root of the files you wish to
|
||||
* be cached. This will also be the directory the service worker and library
|
||||
* files are written to.
|
||||
* @param {Array<String>} input.globPatterns Patterns to glob for when
|
||||
* generating the build manifest.
|
||||
* @param {String|Array<String>} [input.globIgnores] Patterns to exclude when
|
||||
* generating the build manifest.
|
||||
* @param {Object<String,Array|String>} [input.templatedUrls]
|
||||
* If a URL is rendered/templated on the server, its contents may not depend on
|
||||
* a single file. This maps URLs to a list of file names, or to a string
|
||||
* value, that uniquely determines each URL's contents.
|
||||
* @param {String} [input.format] Default format is [`'iife'`](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression), but also
|
||||
* accepts `'es'`, which outputs an ES2015 module.
|
||||
* @return {Promise} Resolves once the service worker has been generated
|
||||
* with a precache list.
|
||||
*
|
||||
* @memberof module:sw-build
|
||||
*/
|
||||
const generateFileManifest = (input) => {
|
||||
if (!input || typeof input !== 'object' || input instanceof Array) {
|
||||
return Promise.reject(
|
||||
new Error(errors['invalid-generate-file-manifest-arg']));
|
||||
}
|
||||
|
||||
const fileEntries = getFileManifestEntries(input);
|
||||
return writeFileManifest(input.dest, fileEntries, input.format);
|
||||
};
|
||||
|
||||
module.exports = generateFileManifest;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-build/src/lib/generate-sw.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const copySWLib = require('./utils/copy-sw-lib');
|
||||
const getFileManifestEntries = require('./get-file-manifest-entries');
|
||||
const writeServiceWorker = require('./write-sw');
|
||||
const errors = require('./errors');
|
||||
|
||||
/**
|
||||
* @example <caption>Generate a service worker for a project.</caption>
|
||||
* const swBuild = require('sw-build');
|
||||
*
|
||||
* swBuild.generateSW({
|
||||
* rootDirectory: './build/',
|
||||
* dest: './build/sw.js',
|
||||
* globPatterns: ['**\/*.{html,js,css}'],
|
||||
* globIgnores: ['admin.html'],
|
||||
* templatedUrls: {
|
||||
* '/shell': ['shell.hbs', 'main.css', 'shell.css'],
|
||||
* },
|
||||
* })
|
||||
* .then(() => {
|
||||
* console.log('Service worker generated.');
|
||||
* });
|
||||
*
|
||||
* This method will generate a working service worker with an inlined
|
||||
* file manifest.
|
||||
* @param {Object} input
|
||||
* @param {String} input.rootDirectory The root of the files you wish to
|
||||
* be cached. This will also be the directory the service worker and library
|
||||
* files are written to.
|
||||
* @param {Array<String>} input.globPatterns Patterns to glob for when
|
||||
* generating the build manifest.
|
||||
* @param {String|Array<String>} [input.globIgnores] Patterns to exclude when
|
||||
* generating the build manifest.
|
||||
* @param {String} input.dest The name you wish to give to your
|
||||
* service worker file.
|
||||
* @param {Object<String,Array|String>} [input.templatedUrls]
|
||||
* If a URL is rendered/templated on the server, its contents may not depend on
|
||||
* a single file. This maps URLs to a list of file names, or to a string
|
||||
* value, that uniquely determines each URL's contents.
|
||||
* @return {Promise} Resolves once the service worker has been generated
|
||||
* with a precache list.
|
||||
*
|
||||
* @memberof module:sw-build
|
||||
*/
|
||||
const generateSW = function(input) {
|
||||
if (!input || typeof input !== 'object' || input instanceof Array) {
|
||||
return Promise.reject(new Error(errors['invalid-generate-sw-input']));
|
||||
}
|
||||
|
||||
const rootDirectory = input.rootDirectory;
|
||||
const globPatterns = input.globPatterns;
|
||||
const globIgnores = input.globIgnores;
|
||||
const dest = input.dest;
|
||||
const templatedUrls = input.templatedUrls;
|
||||
|
||||
if (typeof rootDirectory !== 'string' || rootDirectory.length === 0) {
|
||||
return Promise.reject(
|
||||
new Error(errors['invalid-root-directory']));
|
||||
}
|
||||
|
||||
if (typeof dest !== 'string' || dest.length === 0) {
|
||||
return Promise.reject(
|
||||
new Error(errors['invalid-dest']));
|
||||
}
|
||||
|
||||
let swlibPath;
|
||||
return copySWLib(rootDirectory)
|
||||
.then((libPath) => {
|
||||
swlibPath = libPath;
|
||||
globIgnores.push(swlibPath);
|
||||
})
|
||||
.then(() => {
|
||||
const manifestEntries = getFileManifestEntries(
|
||||
{globPatterns, globIgnores, rootDirectory, templatedUrls});
|
||||
return writeServiceWorker(
|
||||
dest,
|
||||
manifestEntries,
|
||||
swlibPath,
|
||||
rootDirectory
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = generateSW;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-build/src/lib/get-file-manifest-entries.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const errors = require('./errors');
|
||||
const filterFiles = require('./utils/filter-files');
|
||||
const getCompositeDetails = require('./utils/get-composite-details');
|
||||
const getFileDetails = require('./utils/get-file-details');
|
||||
const getStringDetails = require('./utils/get-string-details');
|
||||
|
||||
/**
|
||||
* @typedef {Object} ManifestEntry
|
||||
* @property {String} url The URL to the asset in the manifest.
|
||||
* @property {String} revision The revision details for the file. This is a
|
||||
* hash generated by node based on the file contents.
|
||||
* @memberof module:sw-build
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* To get a list of files and revision details that can be used to ultimately
|
||||
* precache assets in a service worker.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Array<String>} input.globPatterns Patterns used to select files to
|
||||
* include in the file entries.
|
||||
* @param {Array<String>} [input.globIgnores] Patterns used to exclude files
|
||||
* from the file entries.
|
||||
* @param {String} input.rootDirectory The directory run the glob patterns over.
|
||||
* @param {Object<String,Array|String>} [input.templatedUrls]
|
||||
* If a URL is rendered/templated on the server, its contents may not depend on
|
||||
* a single file. This maps URLs to a list of file names, or to a string
|
||||
* value, that uniquely determines each URL's contents.
|
||||
* @return {Array<ManifestEntry>} An array of ManifestEntries will include
|
||||
* a url and revision details for each file found.
|
||||
* @memberof module:sw-build
|
||||
*/
|
||||
const getFileManifestEntries = (input) => {
|
||||
if (!input || typeof input !== 'object' || input instanceof Array) {
|
||||
throw new Error(errors['invalid-get-manifest-entries-input']);
|
||||
}
|
||||
|
||||
const globPatterns = input.globPatterns;
|
||||
const globIgnores = input.globIgnores;
|
||||
const rootDirectory = input.rootDirectory;
|
||||
const templatedUrls = input.templatedUrls;
|
||||
|
||||
if (typeof rootDirectory !== 'string' || rootDirectory.length === 0) {
|
||||
return Promise.reject(
|
||||
new Error(errors['invalid-root-directory']));
|
||||
}
|
||||
|
||||
if (!globPatterns || !Array.isArray(globPatterns)) {
|
||||
return Promise.reject(
|
||||
new Error(errors['invalid-glob-patterns']));
|
||||
}
|
||||
|
||||
const fileSet = new Set();
|
||||
|
||||
const fileDetails = globPatterns.reduce((accumulated, globPattern) => {
|
||||
const globbedFileDetails = getFileDetails(
|
||||
rootDirectory, globPattern, globIgnores);
|
||||
globbedFileDetails.forEach((fileDetails) => {
|
||||
if (fileSet.has(fileDetails.file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fileSet.add(fileDetails.file);
|
||||
accumulated.push(fileDetails);
|
||||
});
|
||||
return accumulated;
|
||||
}, []);
|
||||
|
||||
// templatedUrls is optional.
|
||||
if (templatedUrls) {
|
||||
if (typeof templatedUrls !== 'object') {
|
||||
return Promise.reject(new Error(errors['invalid-templated-urls']));
|
||||
}
|
||||
|
||||
for (let url of Object.keys(templatedUrls)) {
|
||||
if (fileSet.has(url)) {
|
||||
return Promise.reject(
|
||||
new Error(errors['templated-url-matches-glob']));
|
||||
}
|
||||
|
||||
const dependencies = templatedUrls[url];
|
||||
if (Array.isArray(dependencies)) {
|
||||
const dependencyDetails = dependencies.reduce((previous, pattern) => {
|
||||
const globbedFileDetails = getFileDetails(
|
||||
rootDirectory, pattern, globIgnores);
|
||||
return previous.concat(globbedFileDetails);
|
||||
}, []);
|
||||
fileDetails.push(getCompositeDetails(url, dependencyDetails));
|
||||
} else if (typeof dependencies === 'string') {
|
||||
fileDetails.push(getStringDetails(url, dependencies));
|
||||
} else {
|
||||
return Promise.reject(
|
||||
new Error(errors['invalid-templated-urls']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filterFiles(fileDetails);
|
||||
};
|
||||
|
||||
module.exports = getFileManifestEntries;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-build/src/lib/log-helper.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.
|
||||
**/
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
/**
|
||||
* Log helper is just a wrapper around the console to print slightly
|
||||
* nicer / colored messages and could be extended to filter based on log
|
||||
* level.
|
||||
* @private
|
||||
*/
|
||||
class LogHelper {
|
||||
/**
|
||||
* Print a warning message to the console (Colored yellow).
|
||||
* @param {string} msg Message to print to the console
|
||||
* @param {Object} [runtimeInfo] Any information available at runtime that
|
||||
* should be printed to the console.
|
||||
*/
|
||||
warn(msg, runtimeInfo) {
|
||||
let loggedMsg = chalk.yellow(msg);
|
||||
if (runtimeInfo) {
|
||||
loggedMsg += ` ${runtimeInfo}`;
|
||||
}
|
||||
console.warn(loggedMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message to the console (Colored red).
|
||||
* @param {string} msg Message to print to the console
|
||||
* @param {Error} [err] An optional error to print to the console.
|
||||
*/
|
||||
error(msg, err) {
|
||||
console.error(chalk.red(msg));
|
||||
|
||||
if (err && err.stack) {
|
||||
console.error(chalk.red(err.stack));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an info message to the console (Colored dim).
|
||||
* @param {string} msg Message to print to the console
|
||||
*/
|
||||
info(msg) {
|
||||
console.log(chalk.dim(msg));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new LogHelper();
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cache-expiration/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-cache-expiration
|
||||
*
|
||||
* The cache expiration plugin allows you define an expiration and/or
|
||||
* limit on the responses cached.
|
||||
*
|
||||
* This can be used to ensure that responses aren't used when they are stale
|
||||
* and that the cache size doesn't grow endlessly.
|
||||
*
|
||||
* @example <caption>Used as an automatically invoked "plugin".</caption>
|
||||
*
|
||||
* // Add cache expiration plugin to `RequestWrapper`.
|
||||
* const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
* cacheName: 'runtime-cache',
|
||||
* plugins: [
|
||||
* // The cache size will be capped at 10 entries.
|
||||
* new goog.cacheExpiration.Plugin({maxEntries: 10})
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* // Add `RequestWrapper` to a runtime cache handler.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* match: ({url}) => url.domain === 'example.com',
|
||||
* handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper})
|
||||
* });
|
||||
*
|
||||
* @example <caption>To use the cache expiration as it's own module, you can
|
||||
* call the <code>expireEntries()</code> method to clean up the cache.</caption>
|
||||
* expirationPlugin.expireEntries({
|
||||
* cacheName: 'example-cache-name'
|
||||
* });
|
||||
*
|
||||
* @module sw-cache-expiration
|
||||
*/
|
||||
|
||||
import {timestampPropertyName, urlPropertyName} from './lib/constants';
|
||||
import Plugin from './lib/plugin';
|
||||
|
||||
export {
|
||||
timestampPropertyName,
|
||||
urlPropertyName,
|
||||
Plugin,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cache-expiration/src/lib/plugin.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import idb from 'idb';
|
||||
import assert from '../../../../lib/assert';
|
||||
import {
|
||||
idbName,
|
||||
idbVersion,
|
||||
urlPropertyName,
|
||||
timestampPropertyName,
|
||||
} from './constants';
|
||||
import ErrorFactory from './error-factory';
|
||||
|
||||
/**
|
||||
* The cache expiration plugin allows you define an expiration and / or
|
||||
* limit on the responses cached.
|
||||
*
|
||||
* @example
|
||||
* const expirationPlugin = new goog.cacheExpiration.Plugin({
|
||||
* maxEntries: 2,
|
||||
* maxAgeSeconds: 10,
|
||||
* });
|
||||
*
|
||||
* @memberof module:sw-cache-expiration
|
||||
*/
|
||||
class Plugin {
|
||||
/**
|
||||
* Creates a new `Plugin` instance, which is used to remove entries from a
|
||||
* [`Cache`](https://developer.mozilla.org/en-US/docs/Web/API/Cache) once
|
||||
* certain criteria—maximum number of entries, age of entry, or both—is met.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Number} [input.maxEntries] The maximum size of the cache. Entries
|
||||
* will be expired using a LRU policy once the cache reaches this size.
|
||||
* @param {Number} [input.maxAgeSeconds] The maximum age for fresh entries.
|
||||
*/
|
||||
constructor({maxEntries, maxAgeSeconds} = {}) {
|
||||
if (!(maxEntries || maxAgeSeconds)) {
|
||||
throw ErrorFactory.createError('max-entries-or-age-required');
|
||||
}
|
||||
|
||||
if (maxEntries && typeof maxEntries !== 'number') {
|
||||
throw ErrorFactory.createError('max-entries-must-be-number');
|
||||
}
|
||||
|
||||
if (maxAgeSeconds && typeof maxAgeSeconds !== 'number') {
|
||||
throw ErrorFactory.createError('max-age-seconds-must-be-number');
|
||||
}
|
||||
|
||||
this.maxEntries = maxEntries;
|
||||
this.maxAgeSeconds = maxAgeSeconds;
|
||||
|
||||
// These are used to keep track of open IndexDB and Caches for a given name.
|
||||
this._dbs = new Map();
|
||||
this._caches = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise for the IndexedDB database used to keep track of state.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @return {DB} An open DB instance.
|
||||
*/
|
||||
async getDB({cacheName} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
|
||||
const idbId = `${idbName}-${cacheName}`;
|
||||
if (!this._dbs.has(idbId)) {
|
||||
const openDb = await idb.open(idbId, idbVersion, (upgradeDB) => {
|
||||
const objectStore = upgradeDB.createObjectStore(cacheName,
|
||||
{keyPath: urlPropertyName});
|
||||
objectStore.createIndex(timestampPropertyName, timestampPropertyName,
|
||||
{unique: false});
|
||||
});
|
||||
this._dbs.set(idbId, openDb);
|
||||
}
|
||||
|
||||
return this._dbs.get(idbId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise for an open Cache instance named `cacheName`.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @return {Cache} An open Cache instance.
|
||||
*/
|
||||
async getCache({cacheName} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
|
||||
if (!this._caches.has(cacheName)) {
|
||||
const openCache = await caches.open(cacheName);
|
||||
this._caches.set(cacheName, openCache);
|
||||
}
|
||||
|
||||
return this._caches.get(cacheName);
|
||||
}
|
||||
|
||||
/**
|
||||
* A "lifecycle" callback that will be triggered automatically by the
|
||||
* `goog.runtimeCaching` handlers when a `Response` is about to be returned
|
||||
* from a [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) to
|
||||
* the handler. It allows the `Response` to be inspected for freshness and
|
||||
* prevents it from being used if the `Response`'s `Date` header value is
|
||||
* older than the configured `maxAgeSeconds`.
|
||||
*
|
||||
* Developers who are not using `goog.runtimeCaching` would normally not call
|
||||
* this method directly; instead, use [`isResponseFresh`](#isResponseFresh)
|
||||
* to perform the same freshness check.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {Response} input.cachedResponse The `Response` object that's been
|
||||
* read from a cache and whose freshness should be checked.
|
||||
* @param {Number} [input.now] A timestamp. Defaults to the current time.
|
||||
* @return {Response|null} Either the `cachedResponse`, if it's fresh, or
|
||||
* `null` if the `Response` is older than `maxAgeSeconds`.
|
||||
*/
|
||||
cacheWillMatch({cachedResponse, now} = {}) {
|
||||
if (this.isResponseFresh({cachedResponse, now})) {
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a `Response` is fresh, based on the `Response`'s
|
||||
* `Date` header and the configured `maxAgeSeconds`.
|
||||
*
|
||||
* If `maxAgeSeconds` or the `Date` header is not set then it will
|
||||
* default to returning `true`.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Response} input.cachedResponse The `Response` object that's been
|
||||
* read from a cache and whose freshness should be checked.
|
||||
* @param {Number} [input.now] A timestamp. Defaults to the current time.
|
||||
* @return {boolean} Either the `true`, if it's fresh, or `false` if the
|
||||
* `Response` is older than `maxAgeSeconds`.
|
||||
*
|
||||
* @example
|
||||
* expirationPlugin.isResponseFresh({
|
||||
* cachedResponse: responseFromCache
|
||||
* });
|
||||
*/
|
||||
isResponseFresh({cachedResponse, now} = {}) {
|
||||
// Only bother checking for freshness if we have a valid response and if
|
||||
// maxAgeSeconds is set. Otherwise, skip the check and always return true.
|
||||
if (cachedResponse && this.maxAgeSeconds) {
|
||||
assert.isInstance({cachedResponse}, Response);
|
||||
|
||||
const dateHeader = cachedResponse.headers.get('date');
|
||||
if (dateHeader) {
|
||||
if (typeof now === 'undefined') {
|
||||
now = Date.now();
|
||||
}
|
||||
|
||||
const parsedDate = new Date(dateHeader);
|
||||
// If the Date header was invalid for some reason, parsedDate.getTime()
|
||||
// will return NaN, and the comparison will always be false. That means
|
||||
// that an invalid date will be treated as if the response is fresh.
|
||||
if ((parsedDate.getTime() + (this.maxAgeSeconds * 1000)) < now) {
|
||||
// Only return false if all the conditions are met.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A "lifecycle" callback that will be triggered automatically by the
|
||||
* `goog.runtimeCaching` handlers when an entry is added to a cache.
|
||||
*
|
||||
* Developers would normally not call this method directly; instead,
|
||||
* [`updateTimestamp`](#updateTimestamp) combined with
|
||||
* [`expireEntries`](#expireEntries) provides equivalent plugin.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the responses belong to.
|
||||
* @param {Response} input.newResponse The new value in the cache.
|
||||
* @param {string} input.url The URL for the cache entry.
|
||||
* @param {Number} [input.now] A timestamp. Defaults to the current time.
|
||||
*/
|
||||
cacheDidUpdate({cacheName, newResponse, url, now} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
assert.isInstance({newResponse}, Response);
|
||||
|
||||
if (typeof now === 'undefined') {
|
||||
now = Date.now();
|
||||
}
|
||||
|
||||
this.updateTimestamp({cacheName, url, now}).then(() => {
|
||||
this.expireEntries({cacheName, now});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the timestamp stored in IndexedDB for `url` to be equal to `now`.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @param {string} input.url The URL for the entry to update.
|
||||
* @param {Number} [input.now] A timestamp. Defaults to the current time.
|
||||
*
|
||||
* @example
|
||||
* expirationPlugin.updateTimestamp({
|
||||
* cacheName: 'example-cache-name',
|
||||
* url: '/example-url'
|
||||
* });
|
||||
*/
|
||||
async updateTimestamp({cacheName, url, now} = {}) {
|
||||
assert.isType({url}, 'string');
|
||||
assert.isType({cacheName}, 'string');
|
||||
|
||||
if (typeof now === 'undefined') {
|
||||
now = Date.now();
|
||||
}
|
||||
|
||||
const db = await this.getDB({cacheName});
|
||||
const tx = db.transaction(cacheName, 'readwrite');
|
||||
tx.objectStore(cacheName).put({
|
||||
[timestampPropertyName]: now,
|
||||
[urlPropertyName]: url,
|
||||
});
|
||||
|
||||
await tx.complete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expires entries, both based on the the maximum age and the maximum number
|
||||
* of entries, depending on how this instance is configured.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @param {Number} [input.now] A timestamp. Defaults to the current time.
|
||||
* @return {Array<string>} A list of the URLs that were expired.
|
||||
*
|
||||
* @example
|
||||
* expirationPlugin.expireEntries({
|
||||
* cacheName: 'example-cache-name'
|
||||
* });
|
||||
*/
|
||||
async expireEntries({cacheName, now} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
|
||||
if (typeof now === 'undefined') {
|
||||
now = Date.now();
|
||||
}
|
||||
|
||||
// First, expire old entries, if maxAgeSeconds is set.
|
||||
const oldEntries = this.maxAgeSeconds ?
|
||||
await this.findOldEntries({cacheName, now}) :
|
||||
[];
|
||||
|
||||
// Once that's done, check for the maximum size.
|
||||
const extraEntries = this.maxEntries ?
|
||||
await this.findExtraEntries({cacheName}) :
|
||||
[];
|
||||
|
||||
// Use a Set to remove any duplicates following the concatenation, then
|
||||
// convert back into an array.
|
||||
const urls = [...new Set(oldEntries.concat(extraEntries))];
|
||||
await this.deleteFromCacheAndIDB({cacheName, urls});
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expires entries based on the the maximum age.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @param {Number} [input.now] A timestamp.
|
||||
* @return {Array<string>} A list of the URLs that were expired.
|
||||
*/
|
||||
async findOldEntries({cacheName, now} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
assert.isType({now}, 'number');
|
||||
|
||||
const expireOlderThan = now - (this.maxAgeSeconds * 1000);
|
||||
const urls = [];
|
||||
const db = await this.getDB({cacheName});
|
||||
const tx = db.transaction(cacheName, 'readonly');
|
||||
const store = tx.objectStore(cacheName);
|
||||
const timestampIndex = store.index(timestampPropertyName);
|
||||
|
||||
timestampIndex.iterateCursor((cursor) => {
|
||||
if (!cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor.value[timestampPropertyName] < expireOlderThan) {
|
||||
urls.push(cursor.value[urlPropertyName]);
|
||||
}
|
||||
|
||||
cursor.continue();
|
||||
});
|
||||
|
||||
await tx.complete;
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the URLs that should be expired as per the current state of IndexedDB
|
||||
* and the `maxEntries` configuration. A least-recently used policy is
|
||||
* enforced, so if `maxEntries` is `N`, and there are `N + M` URLs listed in
|
||||
* IndexedDB, then this function will return the least-recently used `M` URLs.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @return {Array<string>} A list of the URLs that are candidates for
|
||||
* expiration.
|
||||
*/
|
||||
async findExtraEntries({cacheName} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
|
||||
const urls = [];
|
||||
const db = await this.getDB({cacheName});
|
||||
let tx = db.transaction(cacheName, 'readonly');
|
||||
let store = tx.objectStore(cacheName);
|
||||
let timestampIndex = store.index(timestampPropertyName);
|
||||
const initialCount = await timestampIndex.count();
|
||||
|
||||
if (initialCount > this.maxEntries) {
|
||||
// We need to create a new transaction to make Firefox happy.
|
||||
tx = db.transaction(cacheName, 'readonly');
|
||||
store = tx.objectStore(cacheName);
|
||||
timestampIndex = store.index(timestampPropertyName);
|
||||
|
||||
timestampIndex.iterateCursor((cursor) => {
|
||||
if (!cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
urls.push(cursor.value[urlPropertyName]);
|
||||
|
||||
if (initialCount - urls.length > this.maxEntries) {
|
||||
cursor.continue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await tx.complete;
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes entries corresponding to each of the URLs from both the Cache
|
||||
* Storage API and from IndexedDB.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {string} input.cacheName Name of the cache the Responses belong to.
|
||||
* @param {Array<string>} urls The URLs to delete.
|
||||
*/
|
||||
async deleteFromCacheAndIDB({cacheName, urls} = {}) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
assert.isArrayOfType({urls}, 'string');
|
||||
|
||||
if (urls.length > 0) {
|
||||
const cache = await this.getCache({cacheName});
|
||||
const db = await this.getDB({cacheName});
|
||||
|
||||
await urls.forEach(async (url) => {
|
||||
await cache.delete(url);
|
||||
const tx = db.transaction(cacheName, 'readwrite');
|
||||
const store = tx.objectStore(cacheName);
|
||||
await store.delete(url);
|
||||
await tx.complete;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Plugin;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cacheable-response/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-cacheable-response
|
||||
*
|
||||
* Given a Response object this behaviour determines whether
|
||||
* it's cacheable, based on a specific configuration.
|
||||
*
|
||||
* @example <caption>Used as an automatically invoked
|
||||
* "plugin".</caption>
|
||||
*
|
||||
* // The responses will be cached if the response code is 0, 200, or 404, and
|
||||
* // will not be cached otherwise.
|
||||
* const cacheablePlugin = new goog.cacheableResponse.Plugin({
|
||||
* statuses: [0, 200, 404]
|
||||
* });
|
||||
*
|
||||
* const requestWrapper = new goog.runtimeCaching.RequestWrapper({
|
||||
* cacheName: 'runtime-cache',
|
||||
* plugins: [
|
||||
* cacheablePlugin
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* match: ({url}) => url.domain === 'example.com',
|
||||
* handler: new goog.runtimeCaching.StaleWhileRevalidate({requestWrapper})
|
||||
* });
|
||||
*
|
||||
* @module sw-cacheable-response
|
||||
*/
|
||||
|
||||
import Plugin from './lib/plugin';
|
||||
|
||||
export {Plugin};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cacheable-response/src/lib/plugin.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* Use this plugin to cache responses with certain HTTP status codes or
|
||||
* header values.
|
||||
*
|
||||
* Defining both status codes and headers will cache requests with a matching
|
||||
* status code and a matching header.
|
||||
*
|
||||
* @example
|
||||
* new goog.cacheableResponse.Plugin({
|
||||
* statuses: [0, 200, 404],
|
||||
* headers: {
|
||||
* 'Example-Header-1': 'Header-Value-1'
|
||||
* 'Example-Header-2': 'Header-Value-2'
|
||||
* }
|
||||
* })
|
||||
*
|
||||
* @memberof module:sw-cacheable-response
|
||||
*/
|
||||
class Plugin {
|
||||
/**
|
||||
* Creates a new `Plugin` instance, which stores configuration and logic
|
||||
* to determine whether a `Response` object is cacheable or not.
|
||||
*
|
||||
* If multiple criteria are present (e.g. both `statuses` and `headers`), then
|
||||
* the `Response` needs to meet all of the criteria to be cacheable.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Array<Number>} [input.statuses] The status codes that are
|
||||
* checked when determining whether a `Response` is cacheable.
|
||||
* @param {Object<String,String>} [input.headers] The header values that are
|
||||
* checked when determining whether a `Response` is cacheable.
|
||||
*/
|
||||
constructor({statuses, headers} = {}) {
|
||||
assert.atLeastOne({statuses, headers});
|
||||
if (statuses !== undefined) {
|
||||
assert.isArrayOfType({statuses}, 'number');
|
||||
}
|
||||
if (headers !== undefined) {
|
||||
assert.isType({headers}, 'object');
|
||||
}
|
||||
|
||||
this.statuses = statuses;
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* A "lifecycle" callback that will be triggered automatically by the
|
||||
* `goog.runtimeCaching` handlers prior to an entry being added to a cache.
|
||||
*
|
||||
* Developers would normally not call this method directly; instead,
|
||||
* [`isResponseCacheable`](#isResponseCacheable) provides equivalent behavior
|
||||
* when used outside of `goog.runtimeCaching`.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {Response} input.newResponse The response that might be cached.
|
||||
* @return {boolean} `true` if the `Response` is cacheable, based on the
|
||||
* configuration of this object, and `false` otherwise.
|
||||
*/
|
||||
cacheWillUpdate({response} = {}) {
|
||||
return this.isResponseCacheable({response});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a response to see whether it's cacheable or not, based on the
|
||||
* configuration of this object.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} input
|
||||
* @param {Response} input.newResponse The response that might be cached.
|
||||
* @return {boolean} `true` if the `Response` is cacheable, based on the
|
||||
* configuration of this object, and `false` otherwise.
|
||||
*/
|
||||
isResponseCacheable({response} = {}) {
|
||||
assert.isInstance({response}, Response);
|
||||
let cacheable = true;
|
||||
|
||||
if (this.statuses) {
|
||||
cacheable = this.statuses.includes(response.status);
|
||||
}
|
||||
|
||||
if (this.headers && cacheable) {
|
||||
cacheable = Object.keys(this.headers).some((headerName) => {
|
||||
return response.headers.get(headerName) === this.headers[headerName];
|
||||
});
|
||||
}
|
||||
|
||||
return cacheable;
|
||||
}
|
||||
}
|
||||
|
||||
export default Plugin;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cli/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.
|
||||
**/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const minimist = require('minimist');
|
||||
const updateNotifier = require('update-notifier');
|
||||
const swBuild = require('sw-build');
|
||||
|
||||
const cliLogHelper = require('./lib/log-helper');
|
||||
const pkg = require('../package.json');
|
||||
const generateGlobPattern = require('./lib/utils/generate-glob-pattern');
|
||||
const saveConfigFile = require('./lib/utils/save-config');
|
||||
const getConfigFile = require('./lib/utils/get-config');
|
||||
|
||||
const askForRootOfWebApp = require('./lib/questions/ask-root-of-web-app');
|
||||
const askForServiceWorkerName = require('./lib/questions/ask-sw-name');
|
||||
const askSaveConfigFile = require('./lib/questions/ask-save-config');
|
||||
const askManifestFileName = require('./lib/questions/ask-manifest-name');
|
||||
const askForExtensionsToCache =
|
||||
require('./lib/questions/ask-extensions-to-cache');
|
||||
|
||||
/**
|
||||
* This class is a wrapper to make test easier. This is used by
|
||||
* ./bin/index.js to pass in the args when the CLI is used.
|
||||
*/
|
||||
class SWCli {
|
||||
/**
|
||||
* This is a helper method that allows the test framework to call argv with
|
||||
* arguments without worrying about running as an actual CLI.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} argv The value passed in via process.argv.
|
||||
* @return {Promise} Promise is returned so testing framework knows when
|
||||
* handling the request has finished.
|
||||
*/
|
||||
argv(argv) {
|
||||
updateNotifier({pkg}).notify();
|
||||
|
||||
const cliArgs = minimist(argv);
|
||||
if (cliArgs._.length > 0) {
|
||||
// We have a command
|
||||
return this.handleCommand(cliArgs._[0], cliArgs._.splice(1), cliArgs)
|
||||
.then(() => {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(() => {
|
||||
process.exit(1);
|
||||
});
|
||||
} else {
|
||||
// we have a flag only request
|
||||
return this.handleFlag(cliArgs)
|
||||
.then(() => {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(() => {
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the help text to the terminal.
|
||||
*/
|
||||
printHelpText() {
|
||||
const helpText = fs.readFileSync(
|
||||
path.join(__dirname, 'cli-help.txt'), 'utf8');
|
||||
cliLogHelper.log(helpText);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is no command given to the CLI then the flags will be passed
|
||||
* to this function in case a relevant action can be taken.
|
||||
* @param {object} flags The available flags = require(the command line.
|
||||
* @return {Promise} returns a promise once handled.
|
||||
*/
|
||||
handleFlag(flags) {
|
||||
let handled = false;
|
||||
if (flags.h || flags.help) {
|
||||
this.printHelpText();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (flags.v || flags.version) {
|
||||
cliLogHelper.log(pkg.version);
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// This is a fallback
|
||||
this.printHelpText();
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
/**
|
||||
* If a command is given in the command line args, this method will handle
|
||||
* the appropriate action.
|
||||
* @param {string} command The command name.
|
||||
* @param {object} args The arguments given to this command.
|
||||
* @param {object} flags The flags supplied with the command line.
|
||||
* @return {Promise} A promise for the provided task.
|
||||
*/
|
||||
handleCommand(command, args, flags) {
|
||||
switch (command) {
|
||||
case 'generate:sw':
|
||||
return this._generateSW();
|
||||
case 'generate:manifest':
|
||||
return this._generateBuildManifest();
|
||||
default:
|
||||
cliLogHelper.error(`Invlaid command given '${command}'`);
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will generate a working service worker with a file manifest.
|
||||
* @return {Promise} The promise returned here will be used to exit the
|
||||
* node process cleanly or not.
|
||||
*/
|
||||
_generateSW() {
|
||||
let config = {};
|
||||
|
||||
return getConfigFile()
|
||||
.then((savedConfig) => {
|
||||
if (savedConfig) {
|
||||
config = savedConfig;
|
||||
config.wasSaved = true;
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (!config.rootDirectory) {
|
||||
return askForRootOfWebApp()
|
||||
.then((rDirectory) => {
|
||||
// This will give a pretty relative path:
|
||||
// '' => './'
|
||||
// 'build' => './build/'
|
||||
config.rootDirectory =
|
||||
path.join('.', path.relative(process.cwd(), rDirectory), path.sep);
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (!config.globPatterns) {
|
||||
return askForExtensionsToCache(config.rootDirectory)
|
||||
.then((extensionsToCache) => {
|
||||
config.globPatterns = [
|
||||
generateGlobPattern(config.rootDirectory, extensionsToCache),
|
||||
];
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (!config.dest) {
|
||||
return askForServiceWorkerName()
|
||||
.then((swName) => {
|
||||
const swDest = path.join(config.rootDirectory, swName);
|
||||
config.dest = swDest;
|
||||
config.globIgnores = [
|
||||
swDest,
|
||||
];
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (!config.wasSaved) {
|
||||
return askSaveConfigFile();
|
||||
}
|
||||
// False since it's already saved.
|
||||
return false;
|
||||
})
|
||||
.then((saveConfig) => {
|
||||
if (saveConfig) {
|
||||
return saveConfigFile(config);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
return swBuild.generateSW(config);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a file manifest with revisioning details
|
||||
* that can be used in your service worker for precaching assets.
|
||||
* @return {Promise} Resolves when the node process exits.
|
||||
*/
|
||||
_generateBuildManifest() {
|
||||
let rootDirPath;
|
||||
let fileManifestName;
|
||||
let fileExtentionsToCache;
|
||||
|
||||
return askForRootOfWebApp()
|
||||
.then((rDirectory) => {
|
||||
rootDirPath = rDirectory;
|
||||
return askForExtensionsToCache(rootDirPath);
|
||||
})
|
||||
.then((extensionsToCache) => {
|
||||
fileExtentionsToCache = extensionsToCache;
|
||||
return askManifestFileName();
|
||||
})
|
||||
.then((manifestName) => {
|
||||
fileManifestName = manifestName;
|
||||
})
|
||||
.then(() => {
|
||||
const globPattern = generateGlobPattern(
|
||||
rootDirPath, fileExtentionsToCache);
|
||||
return swBuild.generateFileManifest({
|
||||
rootDirectory: rootDirPath,
|
||||
globPatterns: [globPattern],
|
||||
globIgnores: [
|
||||
path.join(rootDirPath, fileManifestName),
|
||||
],
|
||||
dest: path.join(rootDirPath, fileManifestName),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SWCli;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cli/src/lib/log-helper.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* http://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.
|
||||
**/
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
/**
|
||||
* Log helper is just a wrapper around the console to print slightly
|
||||
* nicer / colored messages and could be extended to filter based on log
|
||||
* level.
|
||||
* @private
|
||||
*/
|
||||
class LogHelper {
|
||||
/**
|
||||
* Print a warning message to the console (Colored yellow).
|
||||
* @param {string} msg Message to print to the console
|
||||
* @param {Object} [runtimeInfo] Any information available at runtime that
|
||||
* should be printed to the console.
|
||||
*/
|
||||
warn(msg, runtimeInfo) {
|
||||
let loggedMsg = chalk.yellow(msg);
|
||||
if (runtimeInfo) {
|
||||
loggedMsg += ` ${runtimeInfo}`;
|
||||
}
|
||||
console.warn(loggedMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message to the console (Colored red).
|
||||
* @param {string} msg Message to print to the console
|
||||
* @param {Error} [err] An optional error to print to the console.
|
||||
*/
|
||||
error(msg, err) {
|
||||
console.error(chalk.red(msg));
|
||||
|
||||
if (err && err.stack) {
|
||||
console.error(chalk.red(err.stack));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an info message to the console (Colored dim).
|
||||
* @param {string} msg Message to print to the console
|
||||
*/
|
||||
log(msg) {
|
||||
console.log(chalk.dim(msg));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new LogHelper();
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-cli/src/lib/questions/ask-root-of-web-app.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const fs = require('fs');
|
||||
const inquirer = require('inquirer');
|
||||
const path = require('path');
|
||||
|
||||
|
||||
const constants = require('../constants');
|
||||
const logHelper = require('../log-helper');
|
||||
const errors = require('../errors');
|
||||
|
||||
/**
|
||||
* This method requests the root directory of the web app.
|
||||
* The user can opt to type in the directory OR select = require(a list of
|
||||
* directories in the current path.
|
||||
* @return {Promise<string>} Promise that resolves with the name of the root
|
||||
* directory if given.
|
||||
*/
|
||||
module.exports = () => {
|
||||
const manualEntryChoice = 'Manually Enter Path';
|
||||
const currentDirectory = process.cwd();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readdir(currentDirectory, (err, directoryContents) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
resolve(directoryContents);
|
||||
});
|
||||
})
|
||||
.then((directoryContents) => {
|
||||
return directoryContents.filter((directoryContent) => {
|
||||
return fs.statSync(directoryContent).isDirectory();
|
||||
});
|
||||
})
|
||||
.then((subdirectories) => {
|
||||
return subdirectories.filter((subdirectory) => {
|
||||
return !constants.blacklistDirectoryNames.includes(subdirectory);
|
||||
});
|
||||
})
|
||||
.then((subdirectories) => {
|
||||
const choices = subdirectories.concat([
|
||||
new inquirer.Separator(),
|
||||
manualEntryChoice,
|
||||
]);
|
||||
return inquirer.prompt([
|
||||
{
|
||||
name: 'rootDir',
|
||||
message: 'What is the root of your web app?',
|
||||
type: 'list',
|
||||
choices: choices,
|
||||
},
|
||||
{
|
||||
name: 'rootDir',
|
||||
message: 'Please manually enter the root of your web app?',
|
||||
when: (answers) => {
|
||||
return answers.rootDir === manualEntryChoice;
|
||||
},
|
||||
},
|
||||
]);
|
||||
})
|
||||
.then((answers) => {
|
||||
return path.join(currentDirectory, answers.rootDir);
|
||||
})
|
||||
.catch((err) => {
|
||||
logHelper.error(
|
||||
errors['unable-to-get-rootdir'],
|
||||
err
|
||||
);
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-lib/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
import ErrorFactory from './lib/error-factory';
|
||||
import SWLib from './lib/sw-lib';
|
||||
import assert from '../../../lib/assert.js';
|
||||
|
||||
if (!assert.isSWEnv()) {
|
||||
// We are not running in a service worker, print error message
|
||||
throw ErrorFactory.createError('not-in-sw');
|
||||
}
|
||||
|
||||
/**
|
||||
* # sw-lib
|
||||
*
|
||||
* A high-level library that makes it easier to configure routes with
|
||||
* caching strategies as well as manage precaching
|
||||
* of assets during the install step of a service worker.
|
||||
*
|
||||
* @example <caption>Adding the Library to your project.</caption>
|
||||
* importScripts('/<Path to Module>/build/sw-lib.min.js');
|
||||
*
|
||||
* @example <caption>Caching assets and registering routes.</caption>
|
||||
*
|
||||
* goog.swlib.cacheRevisionedAssets([
|
||||
* {
|
||||
* url: '/',
|
||||
* revision: '1234'
|
||||
* },
|
||||
* {
|
||||
* url: '/styles/main.css',
|
||||
* revision: 'abcd'
|
||||
* }
|
||||
* ]);
|
||||
*
|
||||
* // Register runtime routes like so.
|
||||
* goog.swlib.router.registerRoute(
|
||||
* '/example/', goog.swlib.staleWhileRevalidate());
|
||||
* goog.swlib.router.registerRoute(
|
||||
* /\/images\/(.*\/)?.*\.(png|jpg|jpeg|gif)/, goog.swlib.cacheFirst());
|
||||
* goog.swlib.router.registerRoute(
|
||||
* '/styles/:filename', goog.swlib.cacheFirst());
|
||||
*
|
||||
* @example <caption>Using plugins with caching strategies.</caption>
|
||||
*
|
||||
* goog.swlib.router.registerRoute(/\/images\/(.*\/)?.*\.(png|jpg|jpeg|gif)/,
|
||||
* goog.swlib.cacheFirst({
|
||||
* cacheName: 'example-cache',
|
||||
* cacheExpiration: {
|
||||
* maxEntries: 10,
|
||||
* maxAgeSeconds: 7 * 24 * 60 * 60
|
||||
* },
|
||||
* cacheableResponse: {
|
||||
* statuses: [0, 200]
|
||||
* },
|
||||
* broadcastCacheUpdate: {
|
||||
* channelName: 'example-channel-name'
|
||||
* },
|
||||
* plugins: [
|
||||
* // Additional Plugins
|
||||
* ]
|
||||
* })
|
||||
* );
|
||||
*
|
||||
* @module sw-lib
|
||||
*/
|
||||
const swLibInstance = new SWLib();
|
||||
export default swLibInstance;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-lib/src/lib/router.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/* eslint-env browser, serviceworker */
|
||||
|
||||
import {
|
||||
Router as SWRoutingRouter,
|
||||
ExpressRoute,
|
||||
RegExpRoute,
|
||||
Route,
|
||||
NavigationRoute,
|
||||
} from '../../../sw-routing/src/index.js';
|
||||
import ErrorFactory from './error-factory.js';
|
||||
|
||||
/**
|
||||
* Adds a friendly API on top of the router from the
|
||||
* {@link module:sw-routing|sw-routing module}.
|
||||
*
|
||||
* @example <caption>How to define a simple route with caching
|
||||
* strategy.</caption>
|
||||
*
|
||||
* goog.swlib.router.registerRoute('/about', goog.swlib.cacheFirst());
|
||||
*
|
||||
* @example <caption>How to define a simple route with custom caching
|
||||
* strategy.</caption>
|
||||
*
|
||||
* self.goog.swlib.router.registerRoute('/about', (args) => {
|
||||
* // The requested URL
|
||||
* console.log(args.url);
|
||||
*
|
||||
* // The FetchEvent to handle
|
||||
* console.log(args.event);
|
||||
*
|
||||
* // The parameters from the matching route (Commonly
|
||||
* // used with Regex / Express routes).
|
||||
* console.log(args.params);
|
||||
*
|
||||
* // Return a promise that resolves with a Response.
|
||||
* return fetch(args.url);
|
||||
* }));
|
||||
*
|
||||
* @memberof module:sw-lib
|
||||
*/
|
||||
class Router extends SWRoutingRouter {
|
||||
/**
|
||||
* Constructs a light wrapper on top of the underlying `Router`.
|
||||
* @param {String} revisionedCacheName The cache name used for entries cached
|
||||
* via cacheRevisionedAssets().
|
||||
*/
|
||||
constructor(revisionedCacheName) {
|
||||
super();
|
||||
this._revisionedCacheName = revisionedCacheName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String|Regex|Route} capture The capture for a route can be one
|
||||
* of three types.
|
||||
* 1. It can be an Express style route, like: '/example/:anything/route/'
|
||||
* The only gotcha with this is that it will only capture URL's on your
|
||||
* origin.
|
||||
* 1. A regex that will be tested against request URL's.
|
||||
* 1. A [Route]{@link module:sw-lib.SWLib#Route} instance.
|
||||
* @param {function|Handler} handler Called when the route is caught by the
|
||||
* capture criteria. The handler argument is ignored if
|
||||
* you pass in a Route object, otherwise it's required.
|
||||
* If required, provide a function or a runtime caching strategy.
|
||||
*/
|
||||
registerRoute(capture, handler) {
|
||||
if (typeof handler === 'function') {
|
||||
handler = {
|
||||
handle: handler,
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof capture === 'string') {
|
||||
if (capture.length === 0) {
|
||||
throw ErrorFactory.createError('empty-express-string');
|
||||
}
|
||||
|
||||
super.registerRoute({
|
||||
route: new ExpressRoute({path: capture, handler}),
|
||||
});
|
||||
} else if (capture instanceof RegExp) {
|
||||
super.registerRoute({
|
||||
route: new RegExpRoute({regExp: capture, handler}),
|
||||
});
|
||||
} else if (capture instanceof Route) {
|
||||
super.registerRoute({route: capture});
|
||||
} else {
|
||||
throw ErrorFactory.createError('unsupported-route-type');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A shortcut used to register a {@link module:sw-routing.NavigationRoute}
|
||||
* instance that will respond to navigation requests using a cache entry for
|
||||
* `url`.
|
||||
*
|
||||
* This is useful when following the [App Shell pattern](https://developers.google.com/web/fundamentals/architecture/app-shell#example-html-for-appshell),
|
||||
* in which the previously cached shell is returned for all navigations.
|
||||
*
|
||||
* The `url` value should correspond to an entry that's already in the cache,
|
||||
* perhaps a URL that is managed by
|
||||
* {@link module:sw-lib.SWLib#cacheRevisionedAssets}. Using a URL that isn't
|
||||
* already cached will lead to failed navigations.
|
||||
*
|
||||
* @param {String} url The URL of the already cached HTML resource.
|
||||
* @param {Object} [options]
|
||||
* @param {Array<RegExp>} [options.blacklist] Defaults to an empty blacklist.
|
||||
* @param {Array<RegExp>} [options.whitelist] Defaults to `[/./]`, which will
|
||||
* match all request URLs.
|
||||
* @param {String} [options.cacheName] The name of the cache which contains
|
||||
* the cached response for `url`. Defaults to the name of the cache
|
||||
* used by cacheRevisionedAssets().
|
||||
*/
|
||||
registerNavigationRoute(url, options = {}) {
|
||||
if (typeof url !== 'string') {
|
||||
throw ErrorFactory.createError('navigation-route-url-string');
|
||||
}
|
||||
|
||||
// Allow folks to explicitly pass in a null/undefined cacheName option if
|
||||
// they want that behavior.
|
||||
const cacheName = 'cacheName' in options ?
|
||||
options.cacheName :
|
||||
this._revisionedCacheName;
|
||||
|
||||
super.registerRoute({route: new NavigationRoute({
|
||||
handler: () => caches.match(url, {cacheName}),
|
||||
whitelist: options.whitelist || [/./],
|
||||
blacklist: options.blacklist || [],
|
||||
})});
|
||||
}
|
||||
}
|
||||
|
||||
export default Router;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-lib/src/lib/sw-lib.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/* eslint-env browser, serviceworker */
|
||||
|
||||
import Router from './router.js';
|
||||
import ErrorFactory from './error-factory.js';
|
||||
import {
|
||||
RevisionedCacheManager, UnrevisionedCacheManager,
|
||||
} from '../../../sw-precaching/src/index.js';
|
||||
import {Route} from '../../../sw-routing/src/index.js';
|
||||
import {Plugin as CacheExpirationPlugin} from
|
||||
'../../../sw-cache-expiration/src/index.js';
|
||||
import {BroadcastCacheUpdatePlugin} from
|
||||
'../../../sw-broadcast-cache-update/src/index.js';
|
||||
import {Plugin as CacheableResponsePlugin} from
|
||||
'../../../sw-cacheable-response/src/index.js';
|
||||
import {
|
||||
CacheFirst, CacheOnly, NetworkFirst,
|
||||
NetworkOnly, StaleWhileRevalidate, RequestWrapper,
|
||||
} from '../../../sw-runtime-caching/src/index.js';
|
||||
|
||||
/**
|
||||
* A high level library to make it as easy as possible to precache assets
|
||||
* efficiently and define run time caching strategies.
|
||||
*
|
||||
* @memberof module:sw-lib
|
||||
*/
|
||||
class SWLib {
|
||||
|
||||
/**
|
||||
* You should never need to instantiate this class. The library instantiates
|
||||
* an instance which can be accessed by `self.goog.swlib`.
|
||||
*/
|
||||
constructor() {
|
||||
this._revisionedCacheManager = new RevisionedCacheManager();
|
||||
this._router = new Router(this._revisionedCacheManager.getCacheName());
|
||||
this._unrevisionedCacheManager = new UnrevisionedCacheManager();
|
||||
this._registerInstallActivateEvents();
|
||||
this._registerDefaultRoutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Revisioned assets can be cached intelligently
|
||||
* during the install (i.e. old files are cleared from the cache, new files
|
||||
* are added to the cache and unchanged files are left as is).
|
||||
*
|
||||
* The input needs to be an array of URL strings which having revisioning
|
||||
* details in them otherwise the entry should be an object with `url` and
|
||||
* `revision` parameters.
|
||||
*
|
||||
* @example <caption>Cache revisioned assets.</caption>
|
||||
* // Cache a set of revisioned URLs
|
||||
* goog.swlib.cacheRevisionedAssets([
|
||||
* '/styles/main.1234.css',
|
||||
* '/images/logo.abcd.jpg'
|
||||
* ]);
|
||||
*
|
||||
* // ...cacheRevisionedAssets() can also take objects to cache
|
||||
* // non-revisioned URLs.
|
||||
* goog.swlib.cacheRevisionedAssets([
|
||||
* {
|
||||
* url: '/index.html',
|
||||
* revision: '1234'
|
||||
* },
|
||||
* {
|
||||
* url: '/about.html',
|
||||
* revision: 'abcd'
|
||||
* }
|
||||
* ]);
|
||||
*
|
||||
* @param {Array<String|Object>} revisionedFiles A set of urls to cache
|
||||
* when the service worker is installed.
|
||||
*/
|
||||
cacheRevisionedAssets(revisionedFiles) {
|
||||
// Add a more helpful error message than assertion error.
|
||||
if (!Array.isArray(revisionedFiles)) {
|
||||
throw ErrorFactory.createError('bad-revisioned-cache-list');
|
||||
}
|
||||
|
||||
this._revisionedCacheManager.addToCacheList({
|
||||
revisionedFiles,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Any assets you wish to cache ahead of time which can't be revisioned
|
||||
* should be cached with this method. All assets are cached on install
|
||||
* regardless of whether an older version of the request is in the cache.
|
||||
*
|
||||
* The input can be a string or a [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request).
|
||||
*
|
||||
* @example <caption>Unrevisioned assets can be cached too.</caption>
|
||||
* // For unrevisioned assets that should always be downloaded
|
||||
* // with every service worker update, use this method.
|
||||
* goog.swlib.warmRuntimeCache([
|
||||
* '/scripts/main.js',
|
||||
* '/images/default-avater.png'
|
||||
* ]);
|
||||
*
|
||||
* // warmRuntimeCache can also accept Requests, in case you need greater
|
||||
* // control over the request.
|
||||
* goog.swlib.warmRuntimeCache([
|
||||
* new Request('/images/logo.png'),
|
||||
* new Request('/api/data.json')
|
||||
* ]);
|
||||
*
|
||||
* @param {Array<String|Request>} unrevisionedFiles A set of urls to cache
|
||||
* when the service worker is installed.
|
||||
*/
|
||||
warmRuntimeCache(unrevisionedFiles) {
|
||||
// Add a more helpful error message than assertion error.
|
||||
if (!Array.isArray(unrevisionedFiles)) {
|
||||
throw ErrorFactory.createError('bad-revisioned-cache-list');
|
||||
}
|
||||
|
||||
this._unrevisionedCacheManager.addToCacheList({
|
||||
unrevisionedFiles,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The router for this library is exposed via the `router` parameter.
|
||||
* This is an instance of the {@link module:sw-lib.Router|Router}.
|
||||
*
|
||||
* @example
|
||||
* self.goog.swlib.router.registerRoute('/', swlib.goog.cacheFirst());
|
||||
*
|
||||
* @type {Router}
|
||||
*/
|
||||
get router() {
|
||||
return this._router;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you need fine grained control of route matching and handling,
|
||||
* use the {@link module:sw-routing.Route|Route Class} to define
|
||||
* the desired plugin and register it to the router.
|
||||
*
|
||||
* This is an export of the
|
||||
* {@link module:sw-routing.Route|sw-runtime Route Class}.
|
||||
*
|
||||
* @example <caption>How to define a route using a Route instance.</caption>
|
||||
*
|
||||
* const routeInstance = new goog.swlib.Route({
|
||||
* match: (url) => {
|
||||
* // Return true or false
|
||||
* return true;
|
||||
* },
|
||||
* handler: {
|
||||
* handle: (args) => {
|
||||
* // The requested URL
|
||||
* console.log(args.url);
|
||||
*
|
||||
* // The FetchEvent to handle
|
||||
* console.log(args.event);
|
||||
*
|
||||
* // The parameters from the matching route.
|
||||
* console.log(args.params);
|
||||
*
|
||||
* // Return a promise that resolves with a Response.
|
||||
* return fetch(args.url);
|
||||
* },
|
||||
* },
|
||||
* });
|
||||
* self.goog.swlib.router.registerRoute(routeInstance);
|
||||
* @type {Route}
|
||||
*/
|
||||
get Route() {
|
||||
return Route;
|
||||
}
|
||||
|
||||
/**
|
||||
* RuntimeStrategyOptions is just a JavaScript object, but the structure
|
||||
* explains the options for runtime strategies used in sw-lib.
|
||||
*
|
||||
* See the example of how this can be used with the `cacheFirst()` caching
|
||||
* strategy.
|
||||
*
|
||||
* @example
|
||||
* const cacheFirstStrategy = goog.swlib.cacheFirst({
|
||||
* cacheName: 'example-cache',
|
||||
* cacheExpiration: {
|
||||
* maxEntries: 10,
|
||||
* maxAgeSeconds: 7 * 24 * 60 * 60
|
||||
* },
|
||||
* broadcastCacheUpdate: {
|
||||
* channelName: 'example-channel-name'
|
||||
* },
|
||||
* cacheableResponse: {
|
||||
* statuses: [0, 200, 404],
|
||||
* headers: {
|
||||
* 'Example-Header-1': 'Header-Value-1'
|
||||
* 'Example-Header-2': 'Header-Value-2'
|
||||
* }
|
||||
* }
|
||||
* plugins: [
|
||||
* // Additional Plugins
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* @typedef {Object} RuntimeStrategyOptions
|
||||
* @property {String} cacheName Name of cache to use
|
||||
* for caching (both lookup and updating).
|
||||
* @property {Object} cacheExpiration Defining this
|
||||
* object will add a cache expiration plugins to this strategy.
|
||||
* @property {Number} cacheExpiration.maxEntries
|
||||
* The maximum number of entries to store in a cache.
|
||||
* @property {Number} cacheExpiration.maxAgeSeconds
|
||||
* The maximum lifetime of a request to stay in the cache before it's removed.
|
||||
* @property {Object} broadcastCacheUpdate Defining
|
||||
* this object will add a broadcast cache update plugin.
|
||||
* @property {String} broadcastCacheUpdate.channelName
|
||||
* The name of the broadcast channel to dispatch messages on.
|
||||
* @property {Array<plugins>} plugins For
|
||||
* any additional plugins you wish to add, simply include them in this
|
||||
* array.
|
||||
* @memberof module:sw-lib.SWLib
|
||||
*/
|
||||
|
||||
/**
|
||||
* A [cache first](https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network)
|
||||
* run-time caching strategy.
|
||||
*
|
||||
* @example
|
||||
* const cacheFirstStrategy = goog.swlib.cacheFirst();
|
||||
*
|
||||
* goog.swlib.router.addRoute('/styles/*', cacheFirstStrategy);
|
||||
*
|
||||
* @param {module:sw-lib.SWLib.RuntimeStrategyOptions} [options] To define
|
||||
* any additional caching or broadcast plugins pass in option values.
|
||||
* @return {module:sw-runtime-caching.CacheFirst} A CacheFirst handler.
|
||||
*/
|
||||
cacheFirst(options) {
|
||||
return this._getCachingMechanism(CacheFirst, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A [cache only](https://jakearchibald.com/2014/offline-cookbook/#cache-only)
|
||||
* run-time caching strategy.
|
||||
*
|
||||
* @example
|
||||
* const cacheOnlyStrategy = goog.swlib.cacheOnly();
|
||||
*
|
||||
* goog.swlib.router.addRoute('/styles/*', cacheOnlyStrategy);
|
||||
*
|
||||
* @param {module:sw-lib.SWLib.RuntimeStrategyOptions} [options] To define
|
||||
* any additional caching or broadcast plugins pass in option values.
|
||||
* @return {module:sw-runtime-caching.CacheOnly} The caching handler instance.
|
||||
*/
|
||||
cacheOnly(options) {
|
||||
return this._getCachingMechanism(CacheOnly, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A [network first](https://jakearchibald.com/2014/offline-cookbook/#network-falling-back-to-cache)
|
||||
* run-time caching strategy.
|
||||
*
|
||||
* @example
|
||||
* const networkFirstStrategy = goog.swlib.networkFirst();
|
||||
*
|
||||
* goog.swlib.router.addRoute('/blog/', networkFirstStrategy);
|
||||
*
|
||||
* @param {module:sw-lib.SWLib.RuntimeStrategyOptions} [options] To define
|
||||
* any additional caching or broadcast plugins pass in option values.
|
||||
* @return {module:sw-runtime-caching.NetworkFirst} The caching handler
|
||||
* instance.
|
||||
*/
|
||||
networkFirst(options) {
|
||||
return this._getCachingMechanism(NetworkFirst, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A [network only](https://jakearchibald.com/2014/offline-cookbook/#network-only)
|
||||
* run-time caching strategy.
|
||||
*
|
||||
* @example
|
||||
* const networkOnlyStrategy = goog.swlib.networkOnly();
|
||||
*
|
||||
* goog.swlib.router.addRoute('/admin/', networkOnlyStrategy);
|
||||
*
|
||||
* @param {module:sw-lib.SWLib.RuntimeStrategyOptions} [options] To define
|
||||
* any additional caching or broadcast plugins pass in option values.
|
||||
* @return {module:sw-runtime-caching.NetworkOnly} The caching handler
|
||||
* instance.
|
||||
*/
|
||||
networkOnly(options) {
|
||||
return this._getCachingMechanism(NetworkOnly, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A [stale while revalidate](https://jakearchibald.com/2014/offline-cookbook/#stale-while-revalidate)
|
||||
* run-time caching strategy.
|
||||
*
|
||||
* @example
|
||||
* const staleWhileRevalidateStrategy = goog.swlib.staleWhileRevalidate();
|
||||
*
|
||||
* goog.swlib.router.addRoute('/styles/*', staleWhileRevalidateStrategy);
|
||||
*
|
||||
* @param {module:sw-lib.SWLib.RuntimeStrategyOptions} [options] To define
|
||||
* any additional caching or broadcast plugins pass in option values.
|
||||
* @return {module:sw-runtime-caching.StaleWhileRevalidate} The caching
|
||||
* handler instance.
|
||||
*/
|
||||
staleWhileRevalidate(options) {
|
||||
return this._getCachingMechanism(StaleWhileRevalidate, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will add plugins based on options passed in by the
|
||||
* developer.
|
||||
*
|
||||
* @private
|
||||
* @param {Class} HandlerClass The class to be configured and instantiated.
|
||||
* @param {Object} [options] Options to configure the handler.
|
||||
* @return {Handler} A handler instance configured with the appropriate
|
||||
* behaviours
|
||||
*/
|
||||
_getCachingMechanism(HandlerClass, options = {}) {
|
||||
const pluginParamsToClass = {
|
||||
'cacheExpiration': CacheExpirationPlugin,
|
||||
'broadcastCacheUpdate': BroadcastCacheUpdatePlugin,
|
||||
'cacheableResponse': CacheableResponsePlugin,
|
||||
};
|
||||
|
||||
const wrapperOptions = {
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
if (options['cacheName']) {
|
||||
wrapperOptions['cacheName'] = options['cacheName'];
|
||||
}
|
||||
|
||||
// Iterate over known plugins and add them to Request Wrapper options.
|
||||
const pluginKeys = Object.keys(pluginParamsToClass);
|
||||
pluginKeys.forEach((pluginKey) => {
|
||||
if (options[pluginKey]) {
|
||||
const PluginClass = pluginParamsToClass[pluginKey];
|
||||
const pluginParams = options[pluginKey];
|
||||
|
||||
wrapperOptions.plugins.push(new PluginClass(pluginParams));
|
||||
}
|
||||
});
|
||||
|
||||
// Add custom plugins.
|
||||
if (options.plugins) {
|
||||
options.plugins.forEach((plugin) => {
|
||||
wrapperOptions.plugins.push(plugin);
|
||||
});
|
||||
}
|
||||
|
||||
return new HandlerClass({
|
||||
requestWrapper: new RequestWrapper(wrapperOptions),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will register listeners for the install and activate events.
|
||||
* @private
|
||||
*/
|
||||
_registerInstallActivateEvents() {
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(Promise.all([
|
||||
this._revisionedCacheManager.install(),
|
||||
this._unrevisionedCacheManager.install(),
|
||||
]));
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(Promise.all([
|
||||
this._revisionedCacheManager.cleanup(),
|
||||
this._unrevisionedCacheManager.cleanup(),
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will register any default routes the library will need.
|
||||
* @private
|
||||
*/
|
||||
_registerDefaultRoutes() {
|
||||
const cacheFirstHandler = this.cacheFirst({
|
||||
cacheName: this._revisionedCacheManager.getCacheName(),
|
||||
});
|
||||
|
||||
const route = new this.Route({
|
||||
match: ({url, event}) => {
|
||||
const cachedUrls = this._revisionedCacheManager.getCachedUrls();
|
||||
return cachedUrls.indexOf(url.href) !== -1;
|
||||
},
|
||||
handler: cacheFirstHandler,
|
||||
});
|
||||
this.router.registerRoute(route);
|
||||
}
|
||||
}
|
||||
|
||||
export default SWLib;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-offline-google-analytics/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/* eslint-env worker, serviceworker */
|
||||
|
||||
import constants from './lib/constants.js';
|
||||
import enqueueRequest from './lib/enqueue-request.js';
|
||||
import logHelper from '../../../lib/log-helper.js';
|
||||
import replayQueuedRequests from './lib/replay-queued-requests.js';
|
||||
|
||||
/**
|
||||
* In order to use the library, call`goog.offlineGoogleAnalytics.initialize()`.
|
||||
* It will take care of setting up service worker `fetch` handlers to ensure
|
||||
* that the Google Analytics JavaScript is available offline, and that any
|
||||
* Google Analytics requests made while offline are saved (using `IndexedDB`)
|
||||
* and retried the next time the service worker starts up.
|
||||
*
|
||||
* @example
|
||||
* // This code should live inside your service worker JavaScript, ideally
|
||||
* // before any other 'fetch' event handlers are defined:
|
||||
*
|
||||
* // First, import the library into the service worker global scope:
|
||||
* importScripts('path/to/offline-google-analytics-import.js');
|
||||
*
|
||||
* // Then, call goog.offlineGoogleAnalytics.initialize():
|
||||
* goog.offlineGoogleAnalytics.initialize();
|
||||
*
|
||||
* // At this point, implement any other service worker caching strategies
|
||||
* // appropriate for your web app.
|
||||
*
|
||||
* @example
|
||||
* // If you need to specify parameters to be sent with each hit, you can use
|
||||
* // the `parameterOverrides` configuration option. This is useful in cases
|
||||
* // where you want to set a custom dimension on all hits sent by the service
|
||||
* // worker to differentiate them in your reports later.
|
||||
* goog.offlineGoogleAnalytics.initialize({
|
||||
* parameterOverrides: {
|
||||
* cd1: 'replay'
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // In situations where you need to programmatically modify a hit's
|
||||
* // parameters you can use the `hitFilter` option. One example of when this
|
||||
* // might be useful is if you wanted to track the amount of time that elapsed
|
||||
* // between when the hit was attempted and when it was successfully replayed.
|
||||
* goog.offlineGoogleAnalytics.initialize({
|
||||
* hitFilter: searchParams =>
|
||||
* // Sets the `qt` param as a custom metric.
|
||||
* const qt = searchParams.get('qt');
|
||||
* searchParams.set('cm1', qt);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @module sw-offline-google-analytics
|
||||
*/
|
||||
|
||||
/**
|
||||
* @alias goog.offlineGoogleAnalytics.initialize
|
||||
* @param {Object=} config
|
||||
* @param {Object=} config.parameterOverrides
|
||||
* [Measurement Protocol parameters](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters),
|
||||
* expressed as key/value pairs, to be added to replayed
|
||||
* Google Analytics requests. This can be used to, e.g., set
|
||||
* a custom dimension indicating that the request was
|
||||
* replayed.
|
||||
* @param {Function=} config.hitFilter
|
||||
* A function that allows you to modify the hit parameters
|
||||
* prior to replaying the hit. The function is invoked with
|
||||
* the original hit's URLSearchParams object as its only
|
||||
* argument. To abort the hit and prevent it from being
|
||||
* replayed, throw an error.
|
||||
* @memberof module:sw-offline-google-analytics
|
||||
*/
|
||||
const initialize = (config) => {
|
||||
config = config || {};
|
||||
|
||||
// Stores whether or not the previous /collect request failed.
|
||||
let previousHitFailed = false;
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
const url = new URL(event.request.url);
|
||||
const request = event.request;
|
||||
|
||||
if (url.hostname === constants.URL.HOST) {
|
||||
if (url.pathname === constants.URL.COLLECT_PATH) {
|
||||
// If this is a /collect request, then use a network-first strategy,
|
||||
// falling back to queueing the request in IndexedDB.
|
||||
|
||||
// Make a clone of the request before we use it, in case we need
|
||||
// to read the request body later on.
|
||||
const clonedRequest = request.clone();
|
||||
|
||||
event.respondWith(
|
||||
fetch(request).then((response) => {
|
||||
if (previousHitFailed) {
|
||||
replayQueuedRequests(config);
|
||||
}
|
||||
previousHitFailed = false;
|
||||
return response;
|
||||
}, (error) => {
|
||||
logHelper.log('Enqueuing failed request...');
|
||||
previousHitFailed = true;
|
||||
return enqueueRequest(clonedRequest).then(() => Response.error());
|
||||
})
|
||||
);
|
||||
} else if (url.pathname === constants.URL.ANALYTICS_JS_PATH) {
|
||||
// If this is a request for the Google Analytics JavaScript library,
|
||||
// use the network first, falling back to the previously cached copy.
|
||||
event.respondWith(
|
||||
caches.open(constants.CACHE_NAME).then((cache) => {
|
||||
return fetch(request).then((response) => {
|
||||
return cache.put(request, response.clone()).then(() => response);
|
||||
}).catch((error) => {
|
||||
logHelper.error(error);
|
||||
return cache.match(request);
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
replayQueuedRequests(config);
|
||||
};
|
||||
|
||||
export default {initialize};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-precaching/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-precaching
|
||||
*
|
||||
* The precaching module provides helpers that make it easy to cache files
|
||||
* during the install step of your service worker.
|
||||
*
|
||||
* The revisioned caching will cache bust requests where appropriate and
|
||||
* only cache assets that have a changed revision asset compared to
|
||||
* the currently cached value.
|
||||
*
|
||||
* @example
|
||||
* importScripts('/<Path to Module>/build/sw-precaching.min.js');
|
||||
*
|
||||
* const revCacheManager = new goog.precaching.RevisionedCacheManager();
|
||||
* revCacheManager.addToCacheList({
|
||||
* revisionedFiles: [
|
||||
* '/styles/main.1234.css',
|
||||
* {
|
||||
* url: '/',
|
||||
* revision: '1234'
|
||||
* }
|
||||
* ],
|
||||
* });
|
||||
*
|
||||
* const unrevCacheManager = new goog.precaching.UnrevisionedCacheManager();
|
||||
* unrevCacheManager.addToCacheList({
|
||||
* unrevisionedFiles: [
|
||||
* '/',
|
||||
* '/images/logo.png'
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* self.addEventListener('install', (event) => {
|
||||
* const promiseChain = Promise.all([
|
||||
* revCacheManager.install(),
|
||||
* unrevCacheManager.install(),
|
||||
* ]);
|
||||
* event.waitUntil(promiseChain);
|
||||
* });
|
||||
*
|
||||
* self.addEventListener('activate', (event) => {
|
||||
* const promiseChain = Promise.all([
|
||||
* revCacheManager.cleanup(),
|
||||
* unrevCacheManager.cleanup()
|
||||
* ]);
|
||||
* event.waitUntil(promiseChain);
|
||||
* });
|
||||
*
|
||||
* @module sw-precaching
|
||||
*/
|
||||
import ErrorFactory from './lib/error-factory';
|
||||
import RevisionedCacheManager from
|
||||
'./lib/controllers/revisioned-cache-manager.js';
|
||||
import UnrevisionedCacheManager from
|
||||
'./lib/controllers/unrevisioned-cache-manager.js';
|
||||
|
||||
import assert from '../../../lib/assert.js';
|
||||
|
||||
if (!assert.isSWEnv()) {
|
||||
// We are not running in a service worker, print error message
|
||||
throw ErrorFactory.createError('not-in-sw');
|
||||
}
|
||||
|
||||
export {
|
||||
RevisionedCacheManager,
|
||||
UnrevisionedCacheManager,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+294
@@ -0,0 +1,294 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-precaching/src/lib/controllers/base-cache-manager.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import ErrorFactory from '../error-factory';
|
||||
import {RequestWrapper} from '../../../../sw-runtime-caching/src/index';
|
||||
/**
|
||||
* This class handles the shared logic for caching revisioned and unrevisioned
|
||||
* assets.
|
||||
* @private
|
||||
* @memberof module:sw-precaching
|
||||
*/
|
||||
class BaseCacheManager {
|
||||
/**
|
||||
* Constructor for BaseCacheManager
|
||||
* @param {String} cacheName This is the cache name to store requested assets.
|
||||
*/
|
||||
constructor(cacheName) {
|
||||
this._entriesToCache = new Map();
|
||||
this._requestWrapper = new RequestWrapper({
|
||||
cacheName,
|
||||
fetchOptions: {
|
||||
credentials: 'same-origin',
|
||||
},
|
||||
});
|
||||
this._cacheName = this._requestWrapper.cacheName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entries to the install list.
|
||||
* This will manage duplicate entries and perform the caching during
|
||||
* the install step.
|
||||
*
|
||||
* @private
|
||||
* @param {Array<String|Request|Object>} rawEntries A raw entry that can be
|
||||
* parsed into a BaseCacheEntry by the inheriting CacheManager.
|
||||
*/
|
||||
_addEntries(rawEntries) {
|
||||
this._parsedCacheUrls = null;
|
||||
|
||||
rawEntries.forEach((rawEntry) => {
|
||||
this._addEntryToInstallList(
|
||||
this._parseEntry(rawEntry)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives access to the cache name used by thie caching manager.
|
||||
* @return {String} The cache name used for this manager.
|
||||
*/
|
||||
getCacheName() {
|
||||
return this._cacheName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of fully qualified URL's that will be cached by this
|
||||
* cache manager.
|
||||
* @return {Array<String>} An array of URLs that will be cached.
|
||||
*/
|
||||
getCachedUrls() {
|
||||
if (!this._parsedCacheUrls) {
|
||||
this._parsedCacheUrls = Array.from(this._entriesToCache.keys())
|
||||
.map((url) => new URL(url, location).href);
|
||||
}
|
||||
|
||||
return this._parsedCacheUrls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the install list.
|
||||
*
|
||||
* Duplicates are filtered out and checks are made for the scenario
|
||||
* where two entries have the same URL but different revisions. For example
|
||||
* caching:
|
||||
* [
|
||||
* {url: '/hello.txt', revision: '1'},
|
||||
* {url: '/hello.txt', revision: '2'},
|
||||
* ]
|
||||
* This will throw an error as the library can't determine the correct
|
||||
* revision and this may cause issues in future when updating the service
|
||||
* worker with new revisions.
|
||||
*
|
||||
* @private
|
||||
* @param {RevisionedCacheEntry} precacheEntry The file entry to be cached
|
||||
* during the next install event.
|
||||
*/
|
||||
_addEntryToInstallList(precacheEntry) {
|
||||
const entryID = precacheEntry.entryID;
|
||||
const previousEntry = this._entriesToCache.get(precacheEntry.entryID);
|
||||
if (!previousEntry) {
|
||||
// This entry isn't in the install list
|
||||
this._entriesToCache.set(entryID, precacheEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
this._onDuplicateInstallEntryFound(precacheEntry, previousEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the service worker install event and caches the revisioned
|
||||
* assets.
|
||||
*
|
||||
* @return {Promise} The promise resolves when all the desired assets are
|
||||
* cached.
|
||||
*/
|
||||
async install() {
|
||||
if (this._entriesToCache.size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cachePromises = [];
|
||||
this._entriesToCache.forEach((precacheEntry) => {
|
||||
cachePromises.push(
|
||||
this._cacheEntry(precacheEntry)
|
||||
);
|
||||
});
|
||||
|
||||
// Wait for all requests to be cached.
|
||||
return Promise.all(cachePromises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the entry and saves it to the cache if the response
|
||||
* is valid.
|
||||
*
|
||||
* @private
|
||||
* @param {BaseCacheEntry} precacheEntry The entry to fetch and cache.
|
||||
* @return {Promise} Returns a promise that resolves once the entry is fetched
|
||||
* and cached.
|
||||
*/
|
||||
async _cacheEntry(precacheEntry) {
|
||||
const isCached = await this._isAlreadyCached(precacheEntry);
|
||||
if (isCached) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this._requestWrapper.fetchAndCache({
|
||||
request: precacheEntry.getNetworkRequest(),
|
||||
waitOnCache: true,
|
||||
cacheKey: precacheEntry.request,
|
||||
});
|
||||
|
||||
return this._onEntryCached(precacheEntry);
|
||||
} catch (err) {
|
||||
throw ErrorFactory.createError('request-not-cached', {
|
||||
message: `Failed to get a cacheable response for ` +
|
||||
`'${precacheEntry.request.url}': ${err.message}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the URL's and determines which assets are no longer required
|
||||
* in the cache.
|
||||
*
|
||||
* This should be called in the service worker activate event.
|
||||
*
|
||||
* @return {Promise} Promise that resolves once the cache entries have been
|
||||
* cleaned.
|
||||
*/
|
||||
async cleanup() {
|
||||
if (!await caches.has(this._cacheName)) {
|
||||
// Cache doesn't exist, so nothing to delete
|
||||
return;
|
||||
}
|
||||
|
||||
const requestsCachedOnInstall = [];
|
||||
this._entriesToCache.forEach((entry) => {
|
||||
requestsCachedOnInstall.push(entry.request.url);
|
||||
});
|
||||
|
||||
const openCache = await this._getCache();
|
||||
const allCachedRequests = await openCache.keys();
|
||||
|
||||
const cachedRequestsToDelete = allCachedRequests.filter((cachedRequest) => {
|
||||
if (requestsCachedOnInstall.includes(cachedRequest.url)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return Promise.all(
|
||||
cachedRequestsToDelete.map((cachedRequest) => {
|
||||
return openCache.delete(cachedRequest);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple helper method to get the open cache used for precaching assets.
|
||||
*
|
||||
* @private
|
||||
* @return {Promise<Cache>} The cache to be used for precaching.
|
||||
*/
|
||||
async _getCache() {
|
||||
if (!this._cache) {
|
||||
this._cache = await caches.open(this._cacheName);
|
||||
}
|
||||
|
||||
return this._cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the file entry in the maniest is valid and
|
||||
* can be parsed as a BaseCacheEntry.
|
||||
*
|
||||
* @private
|
||||
* @abstract
|
||||
* @param {String | Request | Object} input Either a URL string, a Request
|
||||
* or an object with a `url`, `revision` and optional `cacheBust` parameter.
|
||||
* @return {BaseCacheEntry} Returns a parsed version of the file entry.
|
||||
*/
|
||||
_parseEntry(input) {
|
||||
throw ErrorFactory.createError('should-override');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in case subclasses have cache entries that are to be installed
|
||||
* but have the same "entryID".
|
||||
* This means that the user is trying to cache the same thing twice.
|
||||
* Subclasses can use this method to throw an error if there is an edge
|
||||
* case that can't be handled.
|
||||
*
|
||||
* @private
|
||||
* @abstract
|
||||
* @param {BaseCacheEntry} newEntry The entry that is to be cached.
|
||||
* @param {BaseCacheEntry} previous The entry that is currently cached.
|
||||
*/
|
||||
_onDuplicateEntryFound(newEntry, previous) {
|
||||
throw ErrorFactory.createError('should-override');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms whether a fileEntry is already in the cache with the
|
||||
* appropriate revision or not.
|
||||
*
|
||||
* @private
|
||||
* @abstract
|
||||
* @param {BaseCacheEntry} precacheEntry A file entry with `path` and
|
||||
* `revision` parameters.
|
||||
* @return {Promise<Boolean>} Returns true is the fileEntry is already
|
||||
* cached, false otherwise.
|
||||
*/
|
||||
_isAlreadyCached(precacheEntry) {
|
||||
throw ErrorFactory.createError('should-override');
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can use this method for any work that needs to be done once a
|
||||
* URL has been cached.
|
||||
*
|
||||
* @private
|
||||
* @abstract
|
||||
* @param {BaseCacheEntry} precacheEntry A file entry with `path` and
|
||||
* `revision` parameters.
|
||||
* @return {Promise} Returns a Promise that resolves once it's work has
|
||||
* been done.
|
||||
*/
|
||||
_onEntryCached(precacheEntry) {
|
||||
throw ErrorFactory.createError('should-override');
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseCacheManager;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-precaching/src/lib/controllers/revisioned-cache-manager.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import ErrorFactory from '../error-factory';
|
||||
import BaseCacheManager from './base-cache-manager';
|
||||
import RevisionDetailsModel from '../models/revision-details-model';
|
||||
import {defaultRevisionedCacheName} from '../constants';
|
||||
import StringPrecacheEntry from
|
||||
'../models/precache-entries/string-precache-entry';
|
||||
import ObjectPrecacheEntry from
|
||||
'../models/precache-entries/object-precache-entry';
|
||||
import assert from '../../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* This class extends a lot of the internal methods from BaseCacheManager
|
||||
* to manage caching of revisioned assets.
|
||||
*
|
||||
* @private
|
||||
* @memberof module:sw-precaching
|
||||
* @extends {module:sw-precaching.BaseCacheManager}
|
||||
*/
|
||||
class RevisionedCacheManager extends BaseCacheManager {
|
||||
/**
|
||||
* Constructor for RevisionedCacheManager
|
||||
* @param {Object} input
|
||||
* @param {String} [input.cacheName] Define the cache used to stash these
|
||||
* entries.
|
||||
*/
|
||||
constructor({cacheName} = {}) {
|
||||
cacheName = cacheName || defaultRevisionedCacheName;
|
||||
super(cacheName);
|
||||
|
||||
this._revisionDetailsModel = new RevisionDetailsModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will add the entries to the install list.
|
||||
* This will manage duplicate entries and perform the caching during
|
||||
* the install step.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* revisionedManager.addToCacheList({
|
||||
* revisionedFiles: [
|
||||
* '/styles/hello.1234.css',
|
||||
* {
|
||||
* url: '/images/logo.png',
|
||||
* revision: '1234'
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* @param {Array<String|Object>} rawEntries A raw entry that can be
|
||||
* parsed into a BaseCacheEntry.
|
||||
*/
|
||||
addToCacheList({revisionedFiles} = {}) {
|
||||
assert.isInstance({revisionedFiles}, Array);
|
||||
super._addEntries(revisionedFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method ensures that the file entry in the maniest is valid and
|
||||
* can be parsed as a BaseCacheEntry.
|
||||
*
|
||||
* @private
|
||||
* @abstract
|
||||
* @param {String | Object} input Either a URL string
|
||||
* or an object with a `url`, `revision` and optional `cacheBust` parameter.
|
||||
* @return {BaseCacheEntry} Returns a parsed version of the file entry.
|
||||
*/
|
||||
_parseEntry(input) {
|
||||
if (typeof input === 'undefined' || input === null) {
|
||||
throw ErrorFactory.createError('invalid-revisioned-entry',
|
||||
new Error('Invalid file entry: ' + JSON.stringify(input))
|
||||
);
|
||||
}
|
||||
|
||||
let precacheEntry;
|
||||
switch(typeof input) {
|
||||
case 'string':
|
||||
precacheEntry = new StringPrecacheEntry(input);
|
||||
break;
|
||||
case 'object':
|
||||
precacheEntry = new ObjectPrecacheEntry(input);
|
||||
break;
|
||||
default:
|
||||
throw ErrorFactory.createError('invalid-revisioned-entry',
|
||||
new Error('Invalid file entry: ' +
|
||||
JSON.stringify(precacheEntry))
|
||||
);
|
||||
}
|
||||
|
||||
return precacheEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a dupe entry exists, check the revision. If the revisions are the same
|
||||
* it's simply a duplicate entry. If they are different, we have two
|
||||
* identical requests with two different revisions which will put this
|
||||
* module into a bad state.
|
||||
*
|
||||
* @private
|
||||
* @param {BaseCacheEntry} newEntry The entry that is to be cached.
|
||||
* @param {BaseCacheEntry} previousEntry The entry that is currently cached.
|
||||
*/
|
||||
_onDuplicateInstallEntryFound(newEntry, previousEntry) {
|
||||
if (previousEntry.revision !== newEntry.revision) {
|
||||
throw ErrorFactory.createError(
|
||||
'duplicate-entry-diff-revisions',
|
||||
new Error(`${JSON.stringify(previousEntry)} <=> ` +
|
||||
`${JSON.stringify(newEntry)}`));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method confirms with a precacheEntry is already in the cache with the
|
||||
* appropriate revision.
|
||||
* If the revision is known, the requested `precacheEntry.revision` is saved
|
||||
* and the cache entry exists for the `precacheEntry.path` this method
|
||||
* will return true.
|
||||
*
|
||||
* @private
|
||||
* @param {BaseCacheEntry} precacheEntry A entry with `path` and `revision`
|
||||
* parameters.
|
||||
* @return {Promise<Boolean>} Returns true if the precacheEntry is already
|
||||
* cached, false otherwise.
|
||||
*/
|
||||
async _isAlreadyCached(precacheEntry) {
|
||||
const revisionDetails = await
|
||||
this._revisionDetailsModel.get(precacheEntry.entryID);
|
||||
if (revisionDetails !== precacheEntry.revision) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const openCache = await this._getCache();
|
||||
const cachedResponse = await openCache.match(precacheEntry.request);
|
||||
return cachedResponse ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {BaseCacheEntry} precacheEntry A file entry with `path` and
|
||||
* `revision` parameters.
|
||||
*/
|
||||
async _onEntryCached(precacheEntry) {
|
||||
await this._revisionDetailsModel.put(
|
||||
precacheEntry.entryID, precacheEntry.revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method closes the indexdDB helper. This is used for unit testing
|
||||
* to ensure cleanup between tests.
|
||||
* @private
|
||||
*/
|
||||
_close() {
|
||||
this._revisionDetailsModel._close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the URL's and determines which assets are no longer required
|
||||
* in the cache.
|
||||
*
|
||||
* This should be called in the service worker activate event.
|
||||
*
|
||||
* @return {Promise} Promise that resolves once the cache entries have been
|
||||
* cleaned.
|
||||
*/
|
||||
cleanup() {
|
||||
return super.cleanup()
|
||||
.then(() => {
|
||||
return this._close();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default RevisionedCacheManager;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-precaching/src/lib/controllers/unrevisioned-cache-manager.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import ErrorFactory from '../error-factory';
|
||||
import BaseCacheManager from './base-cache-manager';
|
||||
import RequestCacheEntry from '../models/precache-entries/request-entry';
|
||||
import StringPrecacheEntry from
|
||||
'../models/precache-entries/string-precache-entry';
|
||||
import assert from '../../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* This class extends a lot of the internal methods from BaseCacheManager
|
||||
* to manage caching of unrevisioned assets.
|
||||
*
|
||||
* @private
|
||||
* @memberof module:sw-precaching
|
||||
* @extends {module:sw-precaching.BaseCacheManager}
|
||||
*/
|
||||
class UnrevisionedCacheManager extends BaseCacheManager {
|
||||
/**
|
||||
* Constructor for UnreivisionedCacheManager
|
||||
* @param {Object} input
|
||||
* @param {String} [input.cacheName] Define the cache used to stash these
|
||||
* entries.
|
||||
*/
|
||||
constructor({cacheName} = {}) {
|
||||
super(cacheName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will add the entries to the install list.
|
||||
* This will manage duplicate entries and perform the caching during
|
||||
* the install step.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* unrevisionedManager.addToCacheList({
|
||||
* unrevisionedFiles: [
|
||||
* '/styles/hello.css',
|
||||
* new Request('/images/logo.png', {
|
||||
* // Custom Request Options.
|
||||
* })
|
||||
* ]
|
||||
* ]});
|
||||
*
|
||||
* @param {Array<String|Request>} rawEntries A raw entry that can be
|
||||
* parsed into a BaseCacheEntry.
|
||||
*/
|
||||
addToCacheList({unrevisionedFiles} = {}) {
|
||||
assert.isInstance({unrevisionedFiles}, Array);
|
||||
super._addEntries(unrevisionedFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method ensures that the file entry in the maniest is valid and
|
||||
* can be parsed as a BaseCacheEntry.
|
||||
*
|
||||
* @private
|
||||
* @abstract
|
||||
* @param {String | Request} input Either a URL string or a Request.
|
||||
* @return {BaseCacheEntry} Returns a parsed version of the file entry.
|
||||
*/
|
||||
_parseEntry(input) {
|
||||
if (typeof input === 'undefined' || input === null) {
|
||||
throw ErrorFactory.createError('invalid-unrevisioned-entry',
|
||||
new Error('Invalid file entry: ' + JSON.stringify(input)));
|
||||
}
|
||||
|
||||
if (typeof input === 'string') {
|
||||
return new StringPrecacheEntry(input);
|
||||
} else if (input instanceof Request) {
|
||||
return new RequestCacheEntry(input);
|
||||
} else {
|
||||
throw ErrorFactory.createError('invalid-unrevisioned-entry',
|
||||
new Error('Invalid file entry: ' +
|
||||
JSON.stringify(input))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {BaseCacheEntry} newEntry The entry that is to be cached.
|
||||
* @param {BaseCacheEntry} previousEntry The entry that is currently cached.
|
||||
*/
|
||||
_onDuplicateInstallEntryFound(newEntry, previousEntry) {
|
||||
// NOOP. Just ignore duplicate entries.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We always want to override previously cached versions.
|
||||
* @private
|
||||
* @param {BaseCacheEntry} precacheEntry A file entry with `path` and
|
||||
* `revision` parameters.
|
||||
* @return {Promise<Boolean>} Returns true is the fileEntry is already
|
||||
* cached, false otherwise.
|
||||
*/
|
||||
async _isAlreadyCached(precacheEntry) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {BaseCacheEntry} precacheEntry A file entry with `path` and
|
||||
* `revision` parameters.
|
||||
*/
|
||||
_onEntryCached(precacheEntry) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
|
||||
export default UnrevisionedCacheManager;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-precaching/src/lib/models/precache-entries/base-precache-entry.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import {cacheBustParamName} from '../../constants';
|
||||
|
||||
/**
|
||||
* This class is extended by a number of classes that take different inputs
|
||||
* and generates the required fields for a BaseCacheEntry.
|
||||
*
|
||||
* @private
|
||||
* @memberof module:sw-precaching
|
||||
*/
|
||||
class BaseCacheEntry {
|
||||
/**
|
||||
* This constructor expects an object and a number or required fields.
|
||||
* You shouldn't need to use this constructor directly.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {String} input.entryID
|
||||
* @param {String} input.revision
|
||||
* @param {Request} input.request
|
||||
* @param {boolean} input.cacheBust
|
||||
*/
|
||||
constructor({entryID, revision, request, cacheBust}) {
|
||||
this.entryID = entryID;
|
||||
this.revision = revision;
|
||||
this.request = request;
|
||||
this.cacheBust = cacheBust;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required since any revisioned request needs to cache bust.
|
||||
* To ensure this is consistent, CacheManagers will make a network request
|
||||
* using this specially formatted request.
|
||||
*
|
||||
* When caching the response, it will be cached against the origin `request`,
|
||||
* removing lookup for the cachebusted URL.
|
||||
*
|
||||
* @return {Request} Returns a cache busted request if needed, otherwise
|
||||
* a normal request with credentials set to 'same-origin' and redirect set to
|
||||
* follow.
|
||||
*/
|
||||
getNetworkRequest() {
|
||||
if (this.cacheBust !== true) {
|
||||
// For the RequestCacheEntry we should return it to ensure headers are
|
||||
// kept in tact and part of the request.
|
||||
return this.request;
|
||||
}
|
||||
|
||||
let url = this.request.url;
|
||||
const requestOptions = {};
|
||||
|
||||
if (this.cacheBust === true) {
|
||||
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 reponse.
|
||||
requestOptions.cache = 'reload';
|
||||
} else {
|
||||
const parsedURL = new URL(url, location);
|
||||
parsedURL.search += (parsedURL.search ? '&' : '') +
|
||||
encodeURIComponent(cacheBustParamName) + '=' +
|
||||
encodeURIComponent(this.revision);
|
||||
url = parsedURL.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return new Request(url, requestOptions);
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseCacheEntry;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-precaching/src/lib/models/revision-details-model.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import IDBHelper from '../../../../../lib/idb-helper.js';
|
||||
import {dbName, dbVersion, dbStorename} from '../constants';
|
||||
|
||||
/**
|
||||
* This class is a simple model that stores EntryID's with their current
|
||||
* revision. This is used when caching revisioned assets so that only entries
|
||||
* with different revisions are downloaded and updated.
|
||||
*
|
||||
* @private
|
||||
* @memberof module:sw-precaching
|
||||
*/
|
||||
class RevisionDetailsModel {
|
||||
/**
|
||||
* Constructor for RevisionDetails Model.
|
||||
*/
|
||||
constructor() {
|
||||
this._idbHelper = new IDBHelper(dbName, dbVersion, dbStorename);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets the revision details for a given entryID.
|
||||
* @param {String} entryID The ID of the revision.
|
||||
* @return {Promise<String|null>} Returns a revision string or
|
||||
* null if there is no revision information.
|
||||
*/
|
||||
get(entryID) {
|
||||
return this._idbHelper.get(entryID);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method saves the revision details to indexedDB.
|
||||
* @param {String} entryID The ID of the revision.
|
||||
* @param {String} revision The current revision for this entryID.
|
||||
* @return {Promise} Promise that resolves once the data has been saved.
|
||||
*/
|
||||
put(entryID, revision) {
|
||||
return this._idbHelper.put(entryID, revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method closes the indexdDB helper. This is only used for unit testing
|
||||
* to ensure clean state between tests.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_close() {
|
||||
this._idbHelper.close();
|
||||
}
|
||||
}
|
||||
|
||||
export default RevisionDetailsModel;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-routing/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-routing
|
||||
*
|
||||
* A service worker helper library to route request URLs to handlers.
|
||||
*
|
||||
* @module sw-routing
|
||||
*/
|
||||
|
||||
import ExpressRoute from './lib/express-route';
|
||||
import NavigationRoute from './lib/navigation-route';
|
||||
import RegExpRoute from './lib/regexp-route';
|
||||
import Route from './lib/route';
|
||||
import Router from './lib/router';
|
||||
|
||||
export {
|
||||
ExpressRoute,
|
||||
NavigationRoute,
|
||||
RegExpRoute,
|
||||
Route,
|
||||
Router,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-routing/src/lib/express-route.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import ErrorFactory from './error-factory';
|
||||
import Route from './route';
|
||||
import pathToRegExp from 'path-to-regexp';
|
||||
|
||||
/**
|
||||
* `ExpressRoute` is a helper class to make defining Express-style
|
||||
* [Routes]{@link Route} easy.
|
||||
*
|
||||
* Under the hood, it uses the [`path-to-regexp`](https://www.npmjs.com/package/path-to-regexp)
|
||||
* library to transform the `path` parameter into a regular expression, which is
|
||||
* then matched against the URL's path.
|
||||
*
|
||||
* Please note that `ExpressRoute` can only match requests for URLs that are on
|
||||
* the same-origin as the current page. If you need to match cross-origin
|
||||
* requests, you can use either a generic [`Route`]{@link Route} or a
|
||||
* [`RegExpRoute`]{@link RegExpRoute}.
|
||||
*
|
||||
* @example
|
||||
* // Any same-origin requests that start with /path/to and end with one
|
||||
* // additional path segment will match this route, with the last path
|
||||
* // segment passed along to the handler via params.file.
|
||||
* const route = new goog.routing.ExpressRoute({
|
||||
* path: '/path/to/:file',
|
||||
* handler: {
|
||||
* handle: ({event, params}) => {
|
||||
* // params.file will be set based on the request URL that matched.
|
||||
* // Do something that returns a Promise.<Response>, like:
|
||||
* return caches.match(event.request);
|
||||
* },
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-routing
|
||||
* @extends Route
|
||||
*/
|
||||
class ExpressRoute extends Route {
|
||||
/**
|
||||
* Constructor for ExpressRoute.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {string} input.path The path to use for routing.
|
||||
* If the path contains [named parameters](https://github.com/pillarjs/path-to-regexp#named-parameters),
|
||||
* then an Object mapping parameter names to the corresponding value
|
||||
* will be passed to the handler via `params`.
|
||||
* @param {Object} input.handler - An Object with a `handle` method that
|
||||
* will be used to respond to matching requests.
|
||||
* @param {string} [input.method] Only match requests that use this
|
||||
* HTTP method. Defaults to `'GET'` if not specified.
|
||||
*/
|
||||
constructor({path, handler, method}) {
|
||||
if (path.substring(0, 1) !== '/') {
|
||||
throw ErrorFactory.createError('express-route-requires-absolute-path');
|
||||
}
|
||||
|
||||
let keys = [];
|
||||
// keys is populated as a side effect of pathToRegExp. This isn't the nicest
|
||||
// API, but so it goes.
|
||||
// https://github.com/pillarjs/path-to-regexp#usage
|
||||
const regExp = pathToRegExp(path, keys);
|
||||
const match = ({url}) => {
|
||||
// Return null immediately if we have a cross-origin request.
|
||||
if (url.origin !== location.origin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const regexpMatches = url.pathname.match(regExp);
|
||||
// Return null immediately if this route doesn't match.
|
||||
if (!regexpMatches) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the route does match, then collect values for all the named
|
||||
// parameters that were returned in keys.
|
||||
// If there are no named parameters then this will end up returning {},
|
||||
// which is truthy, and therefore a sufficient return value.
|
||||
const namedParamsToValues = {};
|
||||
keys.forEach((key, index) => {
|
||||
namedParamsToValues[key.name] = regexpMatches[index + 1];
|
||||
});
|
||||
|
||||
return namedParamsToValues;
|
||||
};
|
||||
|
||||
super({match, handler, method});
|
||||
}
|
||||
}
|
||||
|
||||
export default ExpressRoute;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-routing/src/lib/navigation-route.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Route from './route';
|
||||
import assert from '../../../../lib/assert';
|
||||
import logHelper from '../../../../lib/log-helper';
|
||||
|
||||
/**
|
||||
* NavigationRoute is a helper class to create a [`Route`]{@link Route}
|
||||
* that matches browser navigation requests, i.e. requests for a page.
|
||||
*
|
||||
* It will only match incoming requests whose [`mode`](https://fetch.spec.whatwg.org/#concept-request-mode)
|
||||
* is set to `navigate`.
|
||||
*
|
||||
* You can optionally only apply this route to a subset of navigation requests
|
||||
* by using one or both of the `blacklist` and `whitelist` parameters. If
|
||||
* both lists are provided, and there's a navigation to a URL which matches
|
||||
* both, then the blacklist will take precedence and the request will not be
|
||||
* matched by this route. The regular expressions in `whitelist` and `blacklist`
|
||||
* are matched against the [`pathname`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname)
|
||||
* portion of the requested URL.
|
||||
*
|
||||
* To match all navigations, use a `whitelist` array containing a RegExp that
|
||||
* matches everything, i.e. `[/./]`.
|
||||
*
|
||||
* @memberof module:sw-routing
|
||||
* @extends Route
|
||||
*
|
||||
* @example
|
||||
* // Any navigation requests that match the whitelist (i.e. URLs whose path
|
||||
* // starts with /article/) will be handled with the cache entry for
|
||||
* // app-shell.html.
|
||||
* const route = new goog.routing.NavigationRoute({
|
||||
* whitelist: [new RegExp('^/article/')],
|
||||
* handler: {handle: () => caches.match('app-shell.html')},
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*/
|
||||
class NavigationRoute extends Route {
|
||||
/**
|
||||
* Constructor for NavigationRoute.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Array<RegExp>} input.whitelist If any of these patterns match,
|
||||
* the route will handle the request (assuming the blacklist doesn't match).
|
||||
* @param {Array<RegExp>} [input.blacklist] If any of these patterns match,
|
||||
* the route will not handle the request (even if a whitelist entry matches).
|
||||
* @param {function} input.handler The handler to manage the response.
|
||||
*/
|
||||
constructor({whitelist, blacklist, handler} = {}) {
|
||||
assert.isArrayOfClass({whitelist}, RegExp);
|
||||
if (blacklist) {
|
||||
assert.isArrayOfClass({blacklist}, RegExp);
|
||||
} else {
|
||||
blacklist = [];
|
||||
}
|
||||
|
||||
const match = ({event, url}) => {
|
||||
let matched = false;
|
||||
let message;
|
||||
|
||||
if (event.request.mode === 'navigate') {
|
||||
if (whitelist.some((regExp) => regExp.test(url.pathname))) {
|
||||
if (blacklist.some((regExp) => regExp.test(url.pathname))) {
|
||||
message = `The navigation route is not being used, since the ` +
|
||||
`request URL matches both the whitelist and blacklist.`;
|
||||
} else {
|
||||
message = `The navigation route is being used.`;
|
||||
matched = true;
|
||||
}
|
||||
} else {
|
||||
message = `The navigation route is not being used, since the ` +
|
||||
`URL being navigated to doesn't match the whitelist.`;
|
||||
}
|
||||
|
||||
logHelper.debug({
|
||||
that: this,
|
||||
message,
|
||||
data: {'request-url': url.href, whitelist, blacklist, handler},
|
||||
});
|
||||
}
|
||||
|
||||
return matched;
|
||||
};
|
||||
|
||||
super({match, handler, method: 'GET'});
|
||||
}
|
||||
}
|
||||
|
||||
export default NavigationRoute;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-routing/src/lib/regexp-route.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Route from './route';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* RegExpRoute is a helper class to make defining regular expression based
|
||||
* [Routes]{@link Route} easy.
|
||||
*
|
||||
* `RegExpRoute` performs its matches against the full request URL, including
|
||||
* the origin. This means that, unlike [`ExpressRoute`]{@link ExpressRoute},
|
||||
* it's able to match cross-origin requests.
|
||||
*
|
||||
* @memberof module:sw-routing
|
||||
* @extends Route
|
||||
*
|
||||
* @example
|
||||
* // Any requests that match the regular expression will match this route, with
|
||||
* // the capture groups passed along to the handler as an array via params.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: new RegExp('^https://example.com/path/to/(\\w+)'),
|
||||
* handler: {
|
||||
* handle: ({event, params}) => {
|
||||
* // params[0], etc. will be set based on the regexp capture groups.
|
||||
* // Do something that returns a Promise.<Response>, like:
|
||||
* return caches.match(event.request);
|
||||
* },
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*/
|
||||
class RegExpRoute extends Route {
|
||||
/**
|
||||
* Constructor for RegExpRoute.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {RegExp} input.regExp The regular expression to match against URLs.
|
||||
* If the `RegExp` contains [capture groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references),
|
||||
* then the array of captured values will be passed to the handler via
|
||||
* `params`.
|
||||
* @param {function} input.handler The handler to manage the response.
|
||||
* @param {string} [input.method] Only match requests that use this
|
||||
* HTTP method. Defaults to `'GET'` if not specified.
|
||||
*/
|
||||
constructor({regExp, handler, method}) {
|
||||
assert.isInstance({regExp}, RegExp);
|
||||
|
||||
const match = ({url}) => {
|
||||
const regexpMatches = url.href.match(regExp);
|
||||
|
||||
// Return null immediately if this route doesn't match.
|
||||
if (!regexpMatches) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the route matches, but there aren't any capture groups defined, then
|
||||
// this will return [], which is truthy and therefore sufficient to
|
||||
// indicate a match.
|
||||
// If there are capture groups, then it will return their values.
|
||||
return regexpMatches.slice(1);
|
||||
};
|
||||
|
||||
super({match, handler, method});
|
||||
}
|
||||
}
|
||||
|
||||
export default RegExpRoute;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-routing/src/lib/route.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import assert from '../../../../lib/assert';
|
||||
import {defaultMethod, validMethods} from './constants';
|
||||
|
||||
/**
|
||||
* A `Route` allows you to tell a service worker that it should handle
|
||||
* certain network requests using a specific response strategy.
|
||||
*
|
||||
* Two configuration options are required:
|
||||
*
|
||||
* - A `match` function, which examines
|
||||
* an incoming [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
||||
* to determine whether this `Route` should apply. The function should return
|
||||
* a [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) value
|
||||
* if the `Route` matches, in which case that return value is passed along to
|
||||
* the `handle` function.
|
||||
* - A `handler` object, which should in turn have a function defined on it
|
||||
* named `handle`. This `handle` function is given the incoming request along
|
||||
* with any additional parameters generated during the `match`, and returns a
|
||||
* Promise for a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
|
||||
*
|
||||
* Instead of implementing your own `handler`, you can use one of the
|
||||
* pre-defined runtime caching strategies from the
|
||||
* {@link module:sw-runtime-caching|sw-runtime-caching} module.
|
||||
*
|
||||
* While you can use `Route` directly, the [`RegExpRoute`]{@link RegExpRoute}
|
||||
* and [`ExpressRoute`]{@link ExpressRoute} subclasses provide a convenient
|
||||
* wrapper with a nicer interface for using regular expressions or Express-style
|
||||
* routes as the `match` criteria.
|
||||
*
|
||||
* @example
|
||||
* // Any navigate requests for URLs that start with /path/to/ will match.
|
||||
* const route = new goog.routing.Route({
|
||||
* match: ({url, event}) => {
|
||||
* return event.request.mode === 'navigate' &&
|
||||
* url.pathname.startsWith('/path/to/');
|
||||
* },
|
||||
* handler: ({event}) => {
|
||||
* // Do something that returns a Promise.<Response>, like:
|
||||
* return caches.match(event.request);
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-routing
|
||||
*/
|
||||
class Route {
|
||||
/**
|
||||
* Constructor for Route class.
|
||||
* @param {Object} input
|
||||
* @param {function} input.match The function that determines whether the
|
||||
* route matches. The function is passed an object with two properties:
|
||||
* `url`, which is a [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL),
|
||||
* and `event`, which is a [FetchEvent](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent).
|
||||
* `match` should return a truthy value when the route applies, and
|
||||
* that value is passed on to the handle function.
|
||||
* @param {function|Object} input.handler A function, or an Object with a
|
||||
* `handle` method. As parameters, the handler is passed an object with
|
||||
* the same `url` and `event` properties as `match` received, along
|
||||
* with an additional property, `params`, set to the truthy value
|
||||
* `match` returned.
|
||||
* @param {string} [input.method] Only match requests that use this
|
||||
* HTTP method. Defaults to `'GET'` if not specified.
|
||||
*/
|
||||
constructor({match, handler, method} = {}) {
|
||||
assert.isType({match}, 'function');
|
||||
if (typeof handler === 'object') {
|
||||
assert.hasMethod({handler}, 'handle');
|
||||
} else {
|
||||
assert.isType({handler}, 'function');
|
||||
}
|
||||
|
||||
|
||||
this.match = match;
|
||||
// Normalize things so that even if the handler is a function, this.handler
|
||||
// gets set to an object with a handle method.
|
||||
this.handler = typeof handler === 'function' ? {handle: handler} : handler;
|
||||
if (method) {
|
||||
assert.isOneOf({method}, validMethods);
|
||||
this.method = method;
|
||||
} else {
|
||||
this.method = defaultMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Route;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-routing/src/lib/router.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Route from './route';
|
||||
import assert from '../../../../lib/assert';
|
||||
import logHelper from '../../../../lib/log-helper.js';
|
||||
|
||||
/**
|
||||
* The Router takes one or more [Routes]{@link Route} and registers a [`fetch`
|
||||
* event listener](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent)
|
||||
* that will respond to network requests if there's a matching route.
|
||||
*
|
||||
* It also allows you to define a "default" handler that applies to any requests
|
||||
* that don't explicitly match a `Route`, and a "catch" handler that responds
|
||||
* to any requests that throw an exception while being routed.
|
||||
*
|
||||
* @memberof module:sw-routing
|
||||
*
|
||||
* @example
|
||||
* // The following example sets up two routes, one to match requests with
|
||||
* // "assets" in their URL, and the other for requests with "images", along
|
||||
* // different runtime caching handlers for each.
|
||||
* // Both the routes are registered with the router, and any requests that
|
||||
* // don't match either route will be handled using the default NetworkFirst
|
||||
* // strategy.
|
||||
* const assetRoute = new RegExpRoute({
|
||||
* regExp: /assets/,
|
||||
* handler: new goog.runtimeCaching.StaleWhileRevalidate(),
|
||||
* });
|
||||
* const imageRoute = new RegExpRoute({
|
||||
* regExp: /images/,
|
||||
* handler: new goog.runtimeCaching.CacheFirst(),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoutes({routes: [assetRoute, imageRoute]});
|
||||
* router.setDefaultHandler({handler: new goog.runtimeCaching.NetworkFirst()});
|
||||
*/
|
||||
class Router {
|
||||
/**
|
||||
* Start with an empty array of routes, and set up the fetch handler.
|
||||
*/
|
||||
constructor() {
|
||||
// _routes will contain a mapping of HTTP method name ('GET', etc.) to an
|
||||
// array of all the corresponding Route instances that are registered.
|
||||
this._routes = new Map();
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
const url = new URL(event.request.url);
|
||||
if (!url.protocol.startsWith('http')) {
|
||||
logHelper.log({
|
||||
that: this,
|
||||
message: 'URL does not start with HTTP and so not passing ' +
|
||||
'through the router.',
|
||||
data: {
|
||||
request: event.request,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let responsePromise;
|
||||
let matchingRoute;
|
||||
for (let route of (this._routes.get(event.request.method) || [])) {
|
||||
const matchResult = route.match({url, event});
|
||||
if (matchResult) {
|
||||
matchingRoute = route;
|
||||
|
||||
logHelper.log({
|
||||
that: this,
|
||||
message: 'The router is founda matching route.',
|
||||
data: {
|
||||
route: matchingRoute,
|
||||
request: event.request,
|
||||
},
|
||||
});
|
||||
|
||||
let params = matchResult;
|
||||
|
||||
if (Array.isArray(params) && params.length === 0) {
|
||||
// Instead of passing an empty array in as params, use undefined.
|
||||
params = undefined;
|
||||
} else if (params.constructor === Object &&
|
||||
Object.keys(params).length === 0) {
|
||||
// Instead of passing an empty object in as params, use undefined.
|
||||
params = undefined;
|
||||
}
|
||||
|
||||
responsePromise = route.handler.handle({url, event, params});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!responsePromise && this.defaultHandler) {
|
||||
responsePromise = this.defaultHandler.handle({url, event});
|
||||
}
|
||||
|
||||
if (responsePromise && this.catchHandler) {
|
||||
responsePromise = responsePromise.catch((error) => {
|
||||
return this.catchHandler.handle({url, event, error});
|
||||
});
|
||||
}
|
||||
|
||||
if (responsePromise) {
|
||||
event.respondWith(responsePromise
|
||||
.then((response) => {
|
||||
logHelper.debug({
|
||||
that: this,
|
||||
message: 'The router is managing a route with a response.',
|
||||
data: {
|
||||
route: matchingRoute,
|
||||
request: event.request,
|
||||
response: response,
|
||||
},
|
||||
});
|
||||
|
||||
return response;
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional default handler will have its handle method called when a
|
||||
* request doesn't have a matching route.
|
||||
*
|
||||
* @example
|
||||
* router.setDefaultHandler({
|
||||
* handler: new goog.runtimeCaching.NetworkFirst()
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Object} input.handler An Object with a `handle` method.
|
||||
*/
|
||||
setDefaultHandler({handler} = {}) {
|
||||
assert.hasMethod({handler}, 'handle');
|
||||
|
||||
this.defaultHandler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a Route throws an error while handling a request, this catch handler
|
||||
* will be called to return an error case.
|
||||
*
|
||||
* @example
|
||||
* router.setCatchHandler({
|
||||
* handler: ({event, params}) => {
|
||||
* return caches.match('/error-page.html');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Object} input.handler An Object with a `handle` method.
|
||||
*/
|
||||
setCatchHandler({handler} = {}) {
|
||||
assert.hasMethod({handler}, 'handle');
|
||||
|
||||
this.catchHandler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register routes will take an array of Routes to register with the
|
||||
* router.
|
||||
*
|
||||
* @example
|
||||
* router.registerRoutes({
|
||||
* routes: [
|
||||
* new RegExpRoute({ ... }),
|
||||
* new ExpressRoute({ ... }),
|
||||
* new Route({ ... }),
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Array.<Route>} input.routes An array of routes to register.
|
||||
*/
|
||||
registerRoutes({routes} = {}) {
|
||||
assert.isArrayOfClass({routes}, Route);
|
||||
|
||||
for (let route of routes) {
|
||||
if (!this._routes.has(route.method)) {
|
||||
this._routes.set(route.method, []);
|
||||
}
|
||||
|
||||
// Give precedence to the most recent route by listing it first.
|
||||
this._routes.get(route.method).unshift(route);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a single route with the router.
|
||||
*
|
||||
* @example
|
||||
* router.registerRoutes({
|
||||
* route: new Route({ ... })
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Route} input.route The route to register.
|
||||
*/
|
||||
registerRoute({route} = {}) {
|
||||
assert.isInstance({route}, Route);
|
||||
|
||||
this.registerRoutes({routes: [route]});
|
||||
}
|
||||
}
|
||||
|
||||
export default Router;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/index.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # sw-runtime-caching
|
||||
*
|
||||
* A service worker helper library that implements various runtime caching
|
||||
* strategies.
|
||||
*
|
||||
* You can learn more about each caching strategy on
|
||||
* {@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/|Jake Archibald's blog post}
|
||||
* which covers various ways of handling fetch events with a service worker.
|
||||
*
|
||||
* @module sw-runtime-caching
|
||||
*/
|
||||
|
||||
import RequestWrapper from './lib/request-wrapper';
|
||||
import CacheFirst from './lib/cache-first';
|
||||
import CacheOnly from './lib/cache-only';
|
||||
import Handler from './lib/handler';
|
||||
import NetworkFirst from './lib/network-first';
|
||||
import NetworkOnly from './lib/network-only';
|
||||
import StaleWhileRevalidate from './lib/stale-while-revalidate';
|
||||
import {defaultCacheName} from './lib/constants';
|
||||
|
||||
export {
|
||||
CacheFirst,
|
||||
CacheOnly,
|
||||
Handler,
|
||||
NetworkFirst,
|
||||
NetworkOnly,
|
||||
RequestWrapper,
|
||||
StaleWhileRevalidate,
|
||||
defaultCacheName,
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/cache-first.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Handler from './handler';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* An implementation of a [cache-first](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network)
|
||||
* request strategy.
|
||||
*
|
||||
* The important thing to note with this caching strategy is that once a
|
||||
* response is cached, it will not be updated. This is useful for assets
|
||||
* that are revisioned as it caches the asset long term and doesn't waste
|
||||
* the user's data.
|
||||
*
|
||||
* @example
|
||||
* // Set up a route to match any requests made for URLs that end in .txt.
|
||||
* // The requests are handled with a cache-first strategy.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: /\.txt$/,
|
||||
* handler: new goog.runtimeCaching.CacheFirst(),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
* @extends Handler
|
||||
*/
|
||||
class CacheFirst extends Handler {
|
||||
/**
|
||||
* The handle method will be called by the
|
||||
* {@link module:sw-routing.Route|Route} class when a route matches a request.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {FetchEvent} input.event The event that triggered the service
|
||||
* worker's fetch handler.
|
||||
* @return {Promise.<Response>} The response, either from the cache,
|
||||
* or if that isn't available, from the network.
|
||||
*/
|
||||
async handle({event} = {}) {
|
||||
assert.isInstance({event}, FetchEvent);
|
||||
|
||||
const cachedResponse = await this.requestWrapper.match({
|
||||
request: event.request,
|
||||
});
|
||||
|
||||
return cachedResponse || await this.requestWrapper.fetchAndCache({
|
||||
request: event.request,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default CacheFirst;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/cache-only.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Handler from './handler';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* An implementation of a [cache-only](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-only)
|
||||
* request strategy.
|
||||
*
|
||||
* The advantage to using this versus directly calling `caches.match()` is that
|
||||
* it will use the cache configuration and trigger the plugins defined in
|
||||
* the underlying `RequestWrapper`.
|
||||
*
|
||||
* @example
|
||||
* // Set up a route to match any requests made for URLs that end in .txt.
|
||||
* // The requests are handled with a cache-only strategy.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: /\.txt$/,
|
||||
* handler: new goog.runtimeCaching.CacheOnly(),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
* @extends Handler
|
||||
*/
|
||||
class CacheOnly extends Handler {
|
||||
/**
|
||||
* The handle method will be called by the
|
||||
* {@link module:sw-routing.Route|Route} class when a route matches a request.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {FetchEvent} input.event The event that triggered the service
|
||||
* worker's fetch handler.
|
||||
* @return {Promise.<Response>} The response from the cache.
|
||||
*/
|
||||
async handle({event} = {}) {
|
||||
assert.isInstance({event}, FetchEvent);
|
||||
|
||||
return await this.requestWrapper.match({request: event.request});
|
||||
}
|
||||
}
|
||||
|
||||
export default CacheOnly;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/constants.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The default cache name, used by
|
||||
* {@link module:sw-runtime-caching.RequestWrapper|RequestWrapper} when there's
|
||||
* no name provided.
|
||||
*
|
||||
* It combines a constant prefix with the `registration.scope` value associated
|
||||
* with the current service worker, ensuring that multiple service workers used
|
||||
* on the same origin will have different default caches.
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof module:sw-runtime-caching
|
||||
*/
|
||||
let cacheName = `sw-runtime-caching`;
|
||||
if (self && self.registration) {
|
||||
cacheName += `-${self.registration.scope}`;
|
||||
}
|
||||
export const defaultCacheName = cacheName;
|
||||
|
||||
/**
|
||||
* A list of the callback method names that the RequestWrapper might trigger.
|
||||
*
|
||||
* @private
|
||||
* @type {Array.<string>}
|
||||
* @memberof module:sw-runtime-caching
|
||||
*/
|
||||
export const pluginCallbacks = [
|
||||
'cacheDidUpdate',
|
||||
'cacheWillMatch',
|
||||
'cacheWillUpdate',
|
||||
'fetchDidFail',
|
||||
'requestWillFetch',
|
||||
];
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/handler.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import RequestWrapper from './request-wrapper';
|
||||
|
||||
/**
|
||||
* This a base class which each caching strategy extends.
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
*/
|
||||
class Handler {
|
||||
/**
|
||||
* Constructor for a new Handler instance.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {RequestWrapper} [input.requestWrapper] An optional `RequestWrapper`
|
||||
* that is used to configure the cache name and request plugins. If
|
||||
* not provided, a new `RequestWrapper` using the
|
||||
* [default cache name](#defaultCacheName) will be used.
|
||||
*/
|
||||
constructor({requestWrapper} = {}) {
|
||||
if (requestWrapper) {
|
||||
this.requestWrapper = requestWrapper;
|
||||
} else {
|
||||
this.requestWrapper = new RequestWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract method that each subclass must implement.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Object} input
|
||||
* @param {FetchEvent} input.event The event that triggered the service
|
||||
* worker's fetch handler.
|
||||
* @param {Object} [input.params] Additional parameters that might be passed
|
||||
* in to the method. If used in conjunction with the
|
||||
* {@link module:sw-routing.Route|Route} class, then the return value
|
||||
* from the `match` function in the Route constructor
|
||||
* will be passed in as the `params` value.
|
||||
* @return {Promise.<Response>} A promise resolving with a response.
|
||||
*/
|
||||
handle({event, params} = {}) {
|
||||
throw Error('This abstract method must be implemented in a subclass.');
|
||||
}
|
||||
}
|
||||
|
||||
export default Handler;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/network-first.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Handler from './handler';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* An implementation of a [network first](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-falling-back-to-cache)
|
||||
* request strategy.
|
||||
*
|
||||
* @example
|
||||
* // Set up a route to match any requests made for URLs that end in .txt.
|
||||
* // The requests are handled with a network-first strategy.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: /\.txt$/,
|
||||
* handler: new goog.runtimeCaching.NetworkFirst(),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
* @extends Handler
|
||||
*/
|
||||
class NetworkFirst extends Handler {
|
||||
/**
|
||||
* Constructor for a new Handler instance.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {number} [input.networkTimeoutSeconds] If set, and a network
|
||||
* response isn't returned timeout is reached, then the cached response
|
||||
* will be returned instead. If there is no previously cached response,
|
||||
* then an `null` response will be returned. This option is meant to
|
||||
* combat "[lie-fi](https://developers.google.com/web/fundamentals/performance/poor-connectivity/#lie-fi)"
|
||||
* scenarios.
|
||||
* @param {RequestWrapper} [input.requestWrapper] An optional `RequestWrapper`
|
||||
* that is used to configure the cache name and request plugins. If
|
||||
* not provided, a new `RequestWrapper` using the
|
||||
* [default cache name](#defaultCacheName) will be used.
|
||||
*/
|
||||
constructor(input = {}) {
|
||||
super(input);
|
||||
|
||||
const {networkTimeoutSeconds} = input;
|
||||
if (networkTimeoutSeconds) {
|
||||
assert.isType({networkTimeoutSeconds}, 'number');
|
||||
this.networkTimeoutSeconds = networkTimeoutSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The handle method will be called by the
|
||||
* {@link module:sw-routing.Route|Route} class when a route matches a request.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {FetchEvent} input.event The event that triggered the service
|
||||
* worker's fetch handler.
|
||||
* @return {Promise.<Response>} The response from the network, or if that's
|
||||
* not available, a previously cached response.
|
||||
*/
|
||||
async handle({event} = {}) {
|
||||
assert.isInstance({event}, FetchEvent);
|
||||
|
||||
const promises = [];
|
||||
let timeoutId;
|
||||
|
||||
if (this.networkTimeoutSeconds) {
|
||||
promises.push(new Promise((resolve) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
resolve(this.requestWrapper.match({request: event.request}));
|
||||
}, this.networkTimeoutSeconds * 1000);
|
||||
}));
|
||||
}
|
||||
|
||||
promises.push(this.requestWrapper.fetchAndCache({request: event.request})
|
||||
.then((response) => {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
return response ?
|
||||
response :
|
||||
Promise.reject('No response received; falling back to cache.');
|
||||
})
|
||||
.catch(() => this.requestWrapper.match({request: event.request}))
|
||||
);
|
||||
|
||||
return Promise.race(promises);
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkFirst;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/network-only.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Handler from './handler';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* An implementation of a [network-only](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-only)
|
||||
* request strategy.
|
||||
*
|
||||
* The advantage to using this versus directly calling `fetch()` is that it will
|
||||
* trigger the plugins defined in the underlying `RequestWrapper`.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* // Set up a route to match any requests made for URLs that end in .txt.
|
||||
* // The requests are handled with a network-only strategy.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: /\.txt$/,
|
||||
* handler: new goog.runtimeCaching.NetworkOnly(),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
* @extends Handler
|
||||
*/
|
||||
class NetworkOnly extends Handler {
|
||||
/**
|
||||
* The handle method will be called by the
|
||||
* {@link module:sw-routing.Route|Route} class when a route matches a request.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {FetchEvent} input.event The event that triggered the service
|
||||
* worker's fetch handler.
|
||||
* @return {Promise.<Response>} The response from the network.
|
||||
*/
|
||||
async handle({event} = {}) {
|
||||
assert.isInstance({event}, FetchEvent);
|
||||
|
||||
return await this.requestWrapper.fetch({request: event.request});
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkOnly;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/request-wrapper.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import assert from '../../../../lib/assert';
|
||||
import logHelper from '../../../../lib/log-helper.js';
|
||||
import {pluginCallbacks, defaultCacheName} from './constants';
|
||||
import ErrorFactory from './error-factory';
|
||||
|
||||
/**
|
||||
* This class is used by the various subclasses of `Handler` to configure the
|
||||
* cache name and any desired plugins, which is to say classes that implement
|
||||
* request lifecycle callbacks.
|
||||
*
|
||||
* It automatically triggers any registered callbacks at the appropriate time.
|
||||
* The current set of plugin callbacks, along with the parameters they're
|
||||
* given and when they're called, is:
|
||||
*
|
||||
* - `cacheWillUpdate({request, response})`: Called prior to writing an entry
|
||||
* to the cache, allowing the callback to decide whether or not the cache
|
||||
* entry should be written.
|
||||
* - `cacheDidUpdate({cacheName, oldResponse, newResponse, url})`: Called
|
||||
* whenever an entry is written to the cache, giving the callback a chance to
|
||||
* notify clients about the update or implement cache expiration.
|
||||
* - `cacheWillMatch({cachedResponse})`: Called whenever a response is read
|
||||
* from the cache and is about to be used, giving the callback a chance to
|
||||
* perform validity/freshness checks.
|
||||
* - `fetchDidFail({request})`: Called whenever a network request fails.
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
*/
|
||||
class RequestWrapper {
|
||||
/**
|
||||
* Constructor for RequestWrapper.
|
||||
* @param {Object} input
|
||||
* @param {string} [input.cacheName] The name of the cache to use for Handlers
|
||||
* that involve caching. If none is provided, a default name that
|
||||
* includes the current service worker scope will be used.
|
||||
* @param {Array.<Object>} [input.plugins] Any plugins that should be
|
||||
* invoked.
|
||||
* @param {Object} [input.fetchOptions] Values passed along to the
|
||||
* [`init`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch#Parameters)
|
||||
* of all `fetch()` requests made by this wrapper.
|
||||
* @param {Object} [input.matchOptions] Values passed along to the
|
||||
* [`options`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match#Parameters)
|
||||
* of all cache `match()` requests made by this wrapper.
|
||||
*/
|
||||
constructor({cacheName, plugins, fetchOptions, matchOptions} = {}) {
|
||||
if (cacheName) {
|
||||
assert.isType({cacheName}, 'string');
|
||||
this.cacheName = cacheName;
|
||||
} else {
|
||||
this.cacheName = defaultCacheName;
|
||||
}
|
||||
|
||||
if (fetchOptions) {
|
||||
assert.isType({fetchOptions}, 'object');
|
||||
this.fetchOptions = fetchOptions;
|
||||
}
|
||||
|
||||
if (matchOptions) {
|
||||
assert.isType({matchOptions}, 'object');
|
||||
this.matchOptions = matchOptions;
|
||||
}
|
||||
|
||||
this.pluginCallbacks = {};
|
||||
|
||||
if (plugins) {
|
||||
assert.isArrayOfType({plugins}, 'object');
|
||||
|
||||
plugins.forEach((plugin) => {
|
||||
for (let callbackName of pluginCallbacks) {
|
||||
if (typeof plugin[callbackName] === 'function') {
|
||||
if (!this.pluginCallbacks[callbackName]) {
|
||||
this.pluginCallbacks[callbackName] = [];
|
||||
}
|
||||
this.pluginCallbacks[callbackName].push(
|
||||
plugin[callbackName].bind(plugin));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.pluginCallbacks.cacheWillUpdate) {
|
||||
if (this.pluginCallbacks.cacheWillUpdate.length !== 1) {
|
||||
throw ErrorFactory.createError('multiple-cache-will-update-plugins');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pluginCallbacks.cacheWillMatch) {
|
||||
if (this.pluginCallbacks.cacheWillMatch.length !== 1) {
|
||||
throw ErrorFactory.createError('multiple-cache-will-match-plugins');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a cache and maintains a reference to that cache
|
||||
* for future use.
|
||||
*
|
||||
* @example
|
||||
* requestWrapper.getCache()
|
||||
* .then((openCache) => {
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
* @return {Promise<Cache>} An open `Cache` instance based on the configured
|
||||
* `cacheName`.
|
||||
*/
|
||||
async getCache() {
|
||||
if (!this._cache) {
|
||||
this._cache = await caches.open(this.cacheName);
|
||||
}
|
||||
return this._cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps `cache.match()`, using the previously configured cache name and match
|
||||
* options.
|
||||
*
|
||||
* @example
|
||||
* requestWrapper.match({event.request})
|
||||
* .then((response) => {
|
||||
* if (!response) {
|
||||
* // No response in cache.
|
||||
* return;
|
||||
* }
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Request|string} input.request The key for the cache lookup.
|
||||
* @return {Promise.<Response>} The cached response.
|
||||
*/
|
||||
async match({request}) {
|
||||
assert.atLeastOne({request});
|
||||
|
||||
const cache = await this.getCache();
|
||||
let cachedResponse = await cache.match(request, this.matchOptions);
|
||||
|
||||
if (this.pluginCallbacks.cacheWillMatch) {
|
||||
cachedResponse = this.pluginCallbacks.cacheWillMatch[0](
|
||||
{cachedResponse});
|
||||
}
|
||||
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps `fetch()`, calls all `requestWillFetch` before making the network
|
||||
* request, and calls any `fetchDidFail` callbacks from the
|
||||
* registered plugins if the request fails.
|
||||
*
|
||||
* @example
|
||||
* requestWrapper.fetch({
|
||||
* request: event.request
|
||||
* })
|
||||
* .then((response) => {
|
||||
* ...
|
||||
* })
|
||||
* .catch((err) => {
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Request|string} input.request The request or URL to be fetched.
|
||||
* @return {Promise.<Response>} The network response.
|
||||
*/
|
||||
async fetch({request}) {
|
||||
assert.atLeastOne({request});
|
||||
const clonedRequest = this.pluginCallbacks.fetchDidFail ?
|
||||
request.clone() : null;
|
||||
if (this.pluginCallbacks.requestWillFetch) {
|
||||
for (let callback of this.pluginCallbacks.requestWillFetch) {
|
||||
const returnedPromise = callback({request});
|
||||
assert.isInstance({returnedPromise}, Promise);
|
||||
const returnedRequest = await returnedPromise;
|
||||
assert.isInstance({returnedRequest}, Request);
|
||||
request = returnedRequest;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return await fetch(request, this.fetchOptions);
|
||||
} catch (err) {
|
||||
if (this.pluginCallbacks.fetchDidFail) {
|
||||
for (let callback of this.pluginCallbacks.fetchDidFail) {
|
||||
callback({request: clonedRequest.clone()});
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines both fetching and caching using the previously configured options
|
||||
* and calling the appropriate plugins.
|
||||
*
|
||||
* By default, responses with a status of [2xx](https://fetch.spec.whatwg.org/#ok-status)
|
||||
* will be considered valid and cacheable, but this could be overridden by
|
||||
* configuring one or more plugins that implement the `cacheWillUpdate`
|
||||
* lifecycle callback.
|
||||
*
|
||||
* @example
|
||||
* requestWrapper.fetchAndCache({
|
||||
* request: event.request
|
||||
* })
|
||||
* .then((response) => {
|
||||
* ...
|
||||
* })
|
||||
* .catch((err) => {
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Request} input.request The request to fetch.
|
||||
* @param {boolean} [input.waitOnCache] `true` means the method should wait
|
||||
* for the cache.put() to complete before returning. The default value
|
||||
* of `false` means return without waiting. It this value is true
|
||||
* and the response can't be cached, an error will be thrown.
|
||||
* @param {Request} [input.cacheKey] Supply a cacheKey if you wish to cache
|
||||
* the response against an alternative request to the `request`
|
||||
* argument.
|
||||
* @return {Promise.<Response>} The network response.
|
||||
*/
|
||||
async fetchAndCache({request, waitOnCache, cacheKey}) {
|
||||
assert.atLeastOne({request});
|
||||
|
||||
let cachingComplete;
|
||||
const response = await this.fetch({request});
|
||||
|
||||
// response.ok is true if the response status is 2xx.
|
||||
// That's the default condition.
|
||||
let cacheable = response.ok;
|
||||
if (this.pluginCallbacks.cacheWillUpdate) {
|
||||
cacheable = this.pluginCallbacks.cacheWillUpdate[0](
|
||||
{request, response});
|
||||
}
|
||||
|
||||
if (cacheable) {
|
||||
const newResponse = response.clone();
|
||||
|
||||
// cacheDelay is a promise that may or may not be used to delay the
|
||||
// completion of this method, depending on the value of `waitOnCache`.
|
||||
cachingComplete = this.getCache().then(async (cache) => {
|
||||
let oldResponse;
|
||||
|
||||
// Only bother getting the old response if the new response isn't opaque
|
||||
// and there's at least one cacheDidUpdateCallbacks. Otherwise, we don't
|
||||
// need it.
|
||||
if (response.type !== 'opaque' &&
|
||||
this.pluginCallbacks.cacheDidUpdate) {
|
||||
oldResponse = await this.match({request});
|
||||
}
|
||||
|
||||
// Regardless of whether or not we'll end up invoking
|
||||
// cacheDidUpdateCallbacks, wait until the cache is updated.
|
||||
const cacheRequest = cacheKey || request;
|
||||
await cache.put(cacheRequest, newResponse);
|
||||
|
||||
for (let callback of (this.pluginCallbacks.cacheDidUpdate || [])) {
|
||||
callback({
|
||||
cacheName: this.cacheName,
|
||||
oldResponse,
|
||||
newResponse,
|
||||
url: request.url,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (!cacheable) {
|
||||
logHelper.debug(`[RequestWrapper] The response for ${request.url}, with
|
||||
a status of ${response.status}, wasn't cached. By default, only
|
||||
responses with a status of 200 are cached. You can configure the
|
||||
cacheableResponse plugin to change this default.`.replace(/\s+/g, ' '));
|
||||
|
||||
if (waitOnCache) {
|
||||
// If the developer request to wait on the cache but the response
|
||||
// isn't cacheable, throw an error.
|
||||
throw ErrorFactory.createError('invalid-reponse-for-caching');
|
||||
}
|
||||
}
|
||||
|
||||
// Only conditionally await the caching completion, giving developers the
|
||||
// option of returning early for, e.g., read-through-caching scenarios.
|
||||
if (waitOnCache && cachingComplete) {
|
||||
await cachingComplete;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
export default RequestWrapper;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
---
|
||||
layout: jsdoc
|
||||
title: "Source: sw-runtime-caching/src/lib/stale-while-revalidate.js"
|
||||
jsdocNav:
|
||||
- Modules:
|
||||
- <a href="module-sw-appcache-behavior.html#main">sw-appcache-behavior</a>
|
||||
- <a href="module-sw-background-sync-queue.html#main">sw-background-sync-queue</a>
|
||||
- <a href="module-sw-broadcast-cache-update.html#main">sw-broadcast-cache-update</a>
|
||||
- <a href="module-sw-build.html#main">sw-build</a>
|
||||
- <a href="module-sw-cache-expiration.html#main">sw-cache-expiration</a>
|
||||
- <a href="module-sw-cacheable-response.html#main">sw-cacheable-response</a>
|
||||
- <a href="module-sw-lib.html#main">sw-lib</a>
|
||||
- <a href="module-sw-offline-google-analytics.html#main">sw-offline-google-analytics</a>
|
||||
- <a href="module-sw-precaching.html#main">sw-precaching</a>
|
||||
- <a href="module-sw-routing.html#main">sw-routing</a>
|
||||
- <a href="module-sw-runtime-caching.html#main">sw-runtime-caching</a>
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/*
|
||||
Copyright 2016 Google Inc. All Rights Reserved.
|
||||
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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
import Handler from './handler';
|
||||
import assert from '../../../../lib/assert';
|
||||
|
||||
/**
|
||||
* An implementation of a [stale-while-revalidate](https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate)
|
||||
* request strategy.
|
||||
*
|
||||
* In addition to updating the appropriate caches, it will also trigger any
|
||||
* appropriate plugins defined in the underlying `RequestWrapper`.
|
||||
*
|
||||
* @example
|
||||
* // Set up a route to match any requests made for URLs that end in .txt.
|
||||
* // The requests are handled with a stale-while-revalidate strategy.
|
||||
* const route = new goog.routing.RegExpRoute({
|
||||
* regExp: /\.txt$/,
|
||||
* handler: new goog.runtimeCaching.StaleWhileRevalidate(),
|
||||
* });
|
||||
*
|
||||
* const router = new goog.routing.Router();
|
||||
* router.registerRoute({route});
|
||||
*
|
||||
* @memberof module:sw-runtime-caching
|
||||
* @extends Handler
|
||||
*/
|
||||
class StaleWhileRevalidate extends Handler {
|
||||
/**
|
||||
* The handle method will be called by the
|
||||
* {@link module:sw-routing.Route|Route} class when a route matches a request.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {FetchEvent} input.event The event that triggered the service
|
||||
* worker's fetch handler.
|
||||
* @return {Promise.<Response>} The response from the cache, if present, or
|
||||
* from the network if not.
|
||||
*/
|
||||
async handle({event} = {}) {
|
||||
assert.isInstance({event}, FetchEvent);
|
||||
|
||||
const fetchAndCacheResponse = this.requestWrapper.fetchAndCache({
|
||||
request: event.request,
|
||||
}).catch(() => Response.error());
|
||||
const cachedResponse = await this.requestWrapper.match({
|
||||
request: event.request,
|
||||
});
|
||||
|
||||
return cachedResponse || await fetchAndCacheResponse;
|
||||
}
|
||||
}
|
||||
|
||||
export default StaleWhileRevalidate;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.19/BackgroundSyncQueue.html
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/SWCli.html
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/SwBuildWebpackPlugin.SwBuildWebpackPlugin.html
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/SwBuildWebpackPlugin.html
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/global.html
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/index.html
|
||||
---
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/module-sw-background-sync-queue.BackgroundSyncQueue.html
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/module-sw-background-sync-queue.html
|
||||
---
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/module-sw-broadcast-cache-update.BroadcastCacheUpdate.html
|
||||
---
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
relPath: reference-docs/stable/v0.0.20/module-sw-broadcast-cache-update.BroadcastCacheUpdatePlugin.html
|
||||
---
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user