mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 10:17:55 +02:00
fix(v2): PWA issues + improve docs (#4377)
* debug pwa * more debugging logs + attempt to upgrade workbox * fix PWA ? * fix PWA ? * enable pwa debugging for deploy previews * try to fix the app installed issue? * try to fix appinstalled not firing * try to add related applications to the PWA manifest * attempt to fix related_applications * attempt to fix related_applications * attempt to fix related_applications * improve PWA strategies * improve PWA doc * refactor/cleanup registerSw * cleanup
This commit is contained in:
parent
efbd8fa351
commit
02cd5d343b
8 changed files with 396 additions and 229 deletions
|
@ -24,9 +24,9 @@
|
|||
"terser-webpack-plugin": "^4.1.0",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"workbox-build": "^6.1.0",
|
||||
"workbox-precaching": "^6.1.0",
|
||||
"workbox-window": "^6.1.0"
|
||||
"workbox-build": "^6.1.1",
|
||||
"workbox-precaching": "^6.1.1",
|
||||
"workbox-window": "^6.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4 || ^17.0.0",
|
||||
|
|
|
@ -10,7 +10,11 @@ const path = require('path');
|
|||
|
||||
const DEFAULT_OPTIONS = {
|
||||
debug: false,
|
||||
offlineModeActivationStrategies: ['appInstalled', 'queryString'],
|
||||
offlineModeActivationStrategies: [
|
||||
'appInstalled',
|
||||
'queryString',
|
||||
'standalone',
|
||||
],
|
||||
injectManifestConfig: {},
|
||||
pwaHead: [],
|
||||
swCustom: undefined,
|
||||
|
@ -23,7 +27,14 @@ exports.PluginOptionSchema = Joi.object({
|
|||
offlineModeActivationStrategies: Joi.array()
|
||||
.items(
|
||||
Joi.string()
|
||||
.valid('appInstalled', 'queryString', 'mobile', 'saveData', 'always')
|
||||
.valid(
|
||||
'appInstalled',
|
||||
'queryString',
|
||||
'standalone',
|
||||
'mobile',
|
||||
'saveData',
|
||||
'always',
|
||||
)
|
||||
.required(),
|
||||
)
|
||||
.default(DEFAULT_OPTIONS.offlineModeActivationStrategies),
|
||||
|
|
|
@ -16,40 +16,91 @@ const PWA_DEBUG = process.env.PWA_DEBUG;
|
|||
|
||||
const debug = PWA_DEBUG; // shortcut
|
||||
|
||||
const MAX_MOBILE_WIDTH = 940;
|
||||
const APP_INSTALLED_EVENT_FIRED_KEY = 'docusaurus.pwa.event.appInstalled.fired';
|
||||
|
||||
async function clearRegistrations() {
|
||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||
if (debug && registrations.length > 0) {
|
||||
if (debug) {
|
||||
console.log(
|
||||
`[Docusaurus-PWA][registerSw]: unregister service workers`,
|
||||
`[Docusaurus-PWA][registerSw]: will unregister all service worker registrations`,
|
||||
registrations,
|
||||
);
|
||||
}
|
||||
await Promise.all(
|
||||
registrations.map(async (registration) => {
|
||||
const result = await registration?.registration?.unregister();
|
||||
if (debug) {
|
||||
console.log(
|
||||
`[Docusaurus-PWA][registerSw]: unregister() service worker registration`,
|
||||
registrations,
|
||||
result,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
if (debug) {
|
||||
console.log(
|
||||
`[Docusaurus-PWA][registerSw]: unregistered all service worker registrations`,
|
||||
registrations,
|
||||
);
|
||||
}
|
||||
registrations.forEach((registration) => {
|
||||
registration.registration.unregister();
|
||||
});
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
const MAX_MOBILE_WIDTH = 940;
|
||||
const APP_INSTALLED_KEY = 'docusaurus.pwa.appInstalled';
|
||||
/*
|
||||
As of 2021:
|
||||
It is complicated and not very reliable to detect an app is actually installed.
|
||||
https://stackoverflow.com/questions/51735869/check-if-user-has-already-installed-pwa-to-homescreen-on-chrome
|
||||
|
||||
- appinstalled event is not in the spec anymore and seems to not fire? https://firt.dev/pwa-2021#less-capabilities-%E2%98%B9%EF%B8%8F
|
||||
- getInstalledRelatedApps() is only supported in recent Chrome and does not seem to reliable either https://github.com/WICG/get-installed-related-apps
|
||||
- display-mode: standalone is not exactly the same concept, but looks like a decent fallback https://petelepage.com/blog/2019/07/is-my-pwa-installed/
|
||||
*/
|
||||
async function isAppInstalledEventFired() {
|
||||
return localStorage.getItem(APP_INSTALLED_EVENT_FIRED_KEY) === 'true';
|
||||
}
|
||||
async function isAppInstalledRelatedApps() {
|
||||
if ('getInstalledRelatedApps' in window.navigator) {
|
||||
const relatedApps = await navigator.getInstalledRelatedApps();
|
||||
return relatedApps.some((app) => app.platform === 'webapp');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isStandaloneDisplayMode() {
|
||||
return window.matchMedia('(display-mode: standalone)').matches;
|
||||
}
|
||||
|
||||
const OfflineModeActivationStrategiesImplementations = {
|
||||
always: () => true,
|
||||
mobile: () => window.innerWidth <= MAX_MOBILE_WIDTH,
|
||||
saveData: () => !!(navigator.connection && navigator.connection.saveData),
|
||||
appInstalled: () => !!localStorage.getItem(APP_INSTALLED_KEY),
|
||||
appInstalled: async () => {
|
||||
const installedEventFired = await isAppInstalledEventFired();
|
||||
const installedRelatedApps = await isAppInstalledRelatedApps();
|
||||
return installedEventFired || installedRelatedApps;
|
||||
},
|
||||
standalone: () => isStandaloneDisplayMode(),
|
||||
queryString: () =>
|
||||
new URLSearchParams(window.location.search).get('offlineMode') === 'true',
|
||||
};
|
||||
|
||||
function isOfflineModeEnabled() {
|
||||
const activeStrategies = PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES.filter(
|
||||
(strategyName) => {
|
||||
const strategyImpl =
|
||||
OfflineModeActivationStrategiesImplementations[strategyName];
|
||||
return strategyImpl();
|
||||
},
|
||||
async function isStrategyActive(strategyName) {
|
||||
return OfflineModeActivationStrategiesImplementations[strategyName]();
|
||||
}
|
||||
|
||||
async function getActiveStrategies() {
|
||||
const activeStrategies = await Promise.all(
|
||||
PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES.map(async (strategyName) => {
|
||||
const isActive = await isStrategyActive(strategyName);
|
||||
return isActive ? strategyName : undefined;
|
||||
}),
|
||||
);
|
||||
return activeStrategies.filter(Boolean); // remove undefined values
|
||||
}
|
||||
|
||||
async function isOfflineModeEnabled() {
|
||||
const activeStrategies = await getActiveStrategies();
|
||||
const enabled = activeStrategies.length > 0;
|
||||
if (debug) {
|
||||
const logObject = {
|
||||
|
@ -85,19 +136,10 @@ function createServiceWorkerUrl(params) {
|
|||
return url;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
console.log('[Docusaurus-PWA][registerSw]: debug mode enabled');
|
||||
}
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
async function registerSW() {
|
||||
const {Workbox} = await import('workbox-window');
|
||||
|
||||
const offlineMode = isOfflineModeEnabled();
|
||||
const offlineMode = await isOfflineModeEnabled();
|
||||
|
||||
const url = createServiceWorkerUrl({offlineMode, debug});
|
||||
const wb = new Workbox(url);
|
||||
|
@ -115,7 +157,7 @@ function createServiceWorkerUrl(params) {
|
|||
sendSkipWaiting();
|
||||
} else if (PWA_RELOAD_POPUP) {
|
||||
const renderReloadPopup = (await import('./renderReloadPopup')).default;
|
||||
renderReloadPopup({
|
||||
await renderReloadPopup({
|
||||
onReload() {
|
||||
wb.addEventListener('controlling', () => {
|
||||
window.location.reload();
|
||||
|
@ -147,12 +189,6 @@ function createServiceWorkerUrl(params) {
|
|||
}
|
||||
}
|
||||
|
||||
// Update service worker if the next one is already in the waiting state.
|
||||
// This happens when the user doesn't click on `reload` in the popup.
|
||||
if (registration.waiting) {
|
||||
handleServiceWorkerWaiting();
|
||||
}
|
||||
|
||||
// Update the current service worker when the next one has finished
|
||||
// installing and transitions to waiting state.
|
||||
wb.addEventListener('waiting', (event) => {
|
||||
|
@ -166,46 +202,98 @@ function createServiceWorkerUrl(params) {
|
|||
// moves to waiting state in another tab.
|
||||
wb.addEventListener('externalwaiting', (event) => {
|
||||
if (debug) {
|
||||
console.log(
|
||||
'[Docusaurus-PWA][registerSw]: event externalwaiting',
|
||||
event,
|
||||
);
|
||||
console.log('[Docusaurus-PWA][registerSw]: event externalwaiting', event);
|
||||
}
|
||||
handleServiceWorkerWaiting();
|
||||
});
|
||||
|
||||
window.addEventListener('appinstalled', (event) => {
|
||||
// Update service worker if the next one is already in the waiting state.
|
||||
// This happens when the user doesn't click on `reload` in the popup.
|
||||
if (registration.waiting) {
|
||||
await handleServiceWorkerWaiting();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO these events still works in chrome but have been removed from the spec in 2019!
|
||||
// See https://github.com/w3c/manifest/pull/836
|
||||
function addLegacyAppInstalledEventsListeners() {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (debug) {
|
||||
console.log(
|
||||
'[Docusaurus-PWA][registerSw]: addLegacyAppInstalledEventsListeners',
|
||||
);
|
||||
}
|
||||
|
||||
window.addEventListener('appinstalled', async (event) => {
|
||||
if (debug) {
|
||||
console.log('[Docusaurus-PWA][registerSw]: event appinstalled', event);
|
||||
}
|
||||
localStorage.setItem(APP_INSTALLED_KEY, true);
|
||||
|
||||
localStorage.setItem(APP_INSTALLED_EVENT_FIRED_KEY, 'true');
|
||||
if (debug) {
|
||||
console.log(
|
||||
"[Docusaurus-PWA][registerSw]: localStorage.setItem(APP_INSTALLED_EVENT_FIRED_KEY, 'true');",
|
||||
);
|
||||
}
|
||||
|
||||
// After the app is installed, we register a service worker with the path
|
||||
// `/sw?enabled`. Since the previous service worker was `/sw`, it'll be
|
||||
// treated as a new one. The previous registration will need to be
|
||||
// cleared, otherwise the reload popup will show.
|
||||
clearRegistrations();
|
||||
await clearRegistrations();
|
||||
});
|
||||
|
||||
window.addEventListener('beforeinstallprompt', (event) => {
|
||||
// TODO this event still works in chrome but has been removed from the spec in 2019!!!
|
||||
window.addEventListener('beforeinstallprompt', async (event) => {
|
||||
if (debug) {
|
||||
console.log('[Docusaurus-PWA][registerSw]: event appinstalled', event);
|
||||
console.log(
|
||||
'[Docusaurus-PWA][registerSw]: event beforeinstallprompt',
|
||||
event,
|
||||
);
|
||||
}
|
||||
// TODO instead of default browser install UI, show custom docusaurus prompt?
|
||||
// event.preventDefault();
|
||||
|
||||
if (localStorage.getItem(APP_INSTALLED_KEY)) {
|
||||
localStorage.removeItem(APP_INSTALLED_KEY);
|
||||
|
||||
if (debug) {
|
||||
console.log(
|
||||
'[Docusaurus-PWA][registerSw]: localStorage.getItem(APP_INSTALLED_EVENT_FIRED_KEY)',
|
||||
localStorage.getItem(APP_INSTALLED_EVENT_FIRED_KEY),
|
||||
);
|
||||
}
|
||||
if (localStorage.getItem(APP_INSTALLED_EVENT_FIRED_KEY)) {
|
||||
localStorage.removeItem(APP_INSTALLED_EVENT_FIRED_KEY);
|
||||
if (debug) {
|
||||
console.log(
|
||||
'[Docusaurus-PWA][registerSw]: localStorage.removeItem(APP_INSTALLED_EVENT_FIRED_KEY)',
|
||||
);
|
||||
}
|
||||
// After uninstalling the app, if the user doesn't clear all data, then
|
||||
// the previous service worker will continue serving cached files. We
|
||||
// need to clear registrations and reload, otherwise the popup will show.
|
||||
clearRegistrations();
|
||||
await clearRegistrations();
|
||||
}
|
||||
});
|
||||
} else if (debug) {
|
||||
|
||||
if (debug) {
|
||||
console.log(
|
||||
'[Docusaurus-PWA][registerSw]: browser does not support service workers',
|
||||
'[Docusaurus-PWA][registerSw]: legacy appinstalled and beforeinstallprompt event listeners installed',
|
||||
);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Init code to run on the client!
|
||||
*/
|
||||
if (typeof window !== 'undefined') {
|
||||
if (debug) {
|
||||
console.log('[Docusaurus-PWA][registerSw]: debug mode enabled');
|
||||
}
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
// First: add the listeners asap/synchronously
|
||||
addLegacyAppInstalledEventsListeners();
|
||||
|
||||
// Then try to register the SW using lazy/dynamic imports
|
||||
registerSW().catch((e) => console.error('registerSW failed', e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,20 +71,37 @@ function getPossibleURLs(url) {
|
|||
const params = parseSwParams();
|
||||
|
||||
const precacheManifest = self.__WB_MANIFEST;
|
||||
const controller = new PrecacheController();
|
||||
const controller = new PrecacheController({
|
||||
fallbackToNetwork: true, // safer to turn this true?
|
||||
});
|
||||
|
||||
if (params.offlineMode) {
|
||||
controller.addToCacheList(precacheManifest);
|
||||
if (params.debug) {
|
||||
console.log('[Docusaurus-PWA][SW]: addToCacheList', {
|
||||
precacheManifest,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await runSWCustomCode(params);
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(controller.install());
|
||||
if (params.debug) {
|
||||
console.log('[Docusaurus-PWA][SW]: install event', {
|
||||
event,
|
||||
});
|
||||
}
|
||||
event.waitUntil(controller.install(event));
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(controller.activate());
|
||||
if (params.debug) {
|
||||
console.log('[Docusaurus-PWA][SW]: activate event', {
|
||||
event,
|
||||
});
|
||||
}
|
||||
event.waitUntil(controller.activate(event));
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', async (event) => {
|
||||
|
@ -95,15 +112,17 @@ function getPossibleURLs(url) {
|
|||
const possibleURL = possibleURLs[i];
|
||||
const cacheKey = controller.getCacheKeyForURL(possibleURL);
|
||||
if (cacheKey) {
|
||||
const cachedResponse = caches.match(cacheKey);
|
||||
if (params.debug) {
|
||||
console.log('[Docusaurus-PWA][SW]: serving cached asset', {
|
||||
requestURL,
|
||||
possibleURL,
|
||||
possibleURLs,
|
||||
cacheKey,
|
||||
cachedResponse,
|
||||
});
|
||||
}
|
||||
event.respondWith(caches.match(cacheKey));
|
||||
event.respondWith(cachedResponse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +130,12 @@ function getPossibleURLs(url) {
|
|||
});
|
||||
|
||||
self.addEventListener('message', async (event) => {
|
||||
if (params.debug) {
|
||||
console.log('[Docusaurus-PWA][SW]: message event', {
|
||||
event,
|
||||
});
|
||||
}
|
||||
|
||||
const type = event.data && event.data.type;
|
||||
|
||||
if (type === 'SKIP_WAITING') {
|
||||
|
|
|
@ -25,7 +25,11 @@ module.exports = {
|
|||
'@docusaurus/plugin-pwa',
|
||||
{
|
||||
debug: true,
|
||||
offlineModeActivationStrategies: ['appInstalled', 'queryString'],
|
||||
offlineModeActivationStrategies: [
|
||||
'appInstalled',
|
||||
'standalone',
|
||||
'queryString',
|
||||
],
|
||||
pwaHead: [
|
||||
{
|
||||
tagName: 'link',
|
||||
|
@ -63,6 +67,12 @@ If your browser supports it, you should be able to install a Docusaurus site as
|
|||
|
||||

|
||||
|
||||
:::note
|
||||
|
||||
App installation requires the https protocol and a valid manifest.
|
||||
|
||||
:::
|
||||
|
||||
## Offline mode (precaching)
|
||||
|
||||
We enable users to browse a Docusaurus site offline, by using service-worker precaching.
|
||||
|
@ -102,11 +112,12 @@ Turn debug mode on:
|
|||
### `offlineModeActivationStrategies`
|
||||
|
||||
- Type: `Array<'appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always'>`
|
||||
- Default: `['appInstalled','queryString']`
|
||||
- Default: `['appInstalled','queryString','standalone']`
|
||||
|
||||
Strategies used to turn the offline mode on:
|
||||
|
||||
- `appInstalled`: activates for users having installed the site as an app
|
||||
- `appInstalled`: activates for users having installed the site as an app (not 100% reliable)
|
||||
- `standalone`: activates for users running the app as standalone (often the case once a PWA is installed)
|
||||
- `queryString`: activates if queryString contains `offlineMode=true` (convenient for PWA debugging)
|
||||
- `mobile`: activates for mobile users (width <= 940px)
|
||||
- `saveData`: activates for users with `navigator.connection.saveData === true`
|
||||
|
@ -118,6 +129,16 @@ Use this carefully: some users may not like to be forced to use the offline mode
|
|||
|
||||
:::
|
||||
|
||||
:::danger
|
||||
|
||||
It is not possible to detect if an as a PWA in a very reliable way.
|
||||
|
||||
The `appinstalled` event has been [removed from the specification](https://github.com/w3c/manifest/pull/836), and the [`navigator.getInstalledRelatedApps()`](https://web.dev/get-installed-related-apps/) API is only supported in recent Chrome versions and require `related_applications` declared in the manifest.
|
||||
|
||||
The [`standalone` strategy](https://petelepage.com/blog/2019/07/is-my-pwa-installed/) is a nice fallback to activate the offline mode (at least when running the installed app).
|
||||
|
||||
:::
|
||||
|
||||
### `injectManifestConfig`
|
||||
|
||||
[Workbox options](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.injectManifest) to pass to `workbox.injectManifest()`. This gives you control over which assets will be precached, and be available offline.
|
||||
|
@ -278,3 +299,15 @@ The module should have a `default` function export, and receives some params.
|
|||
Adds an entry before the Docusaurus app so that registration can happen before the app runs. The default `registerSW.js` file is enough for simple registration.
|
||||
|
||||
Passing `false` will disable registration entirely.
|
||||
|
||||
## Manifest example
|
||||
|
||||
The Docusaurus site manifest can serve as an inspiration:
|
||||
|
||||
```mdx-code-block
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
<CodeBlock className="language-json">
|
||||
{JSON.stringify(require("@site/static/manifest.json"),null,2)}
|
||||
</CodeBlock>
|
||||
```
|
||||
|
|
|
@ -162,8 +162,12 @@ const LocaleConfigs = isI18nStaging
|
|||
[
|
||||
'@docusaurus/plugin-pwa',
|
||||
{
|
||||
debug: false,
|
||||
offlineModeActivationStrategies: ['appInstalled', 'queryString'],
|
||||
debug: isDeployPreview,
|
||||
offlineModeActivationStrategies: [
|
||||
'appInstalled',
|
||||
'standalone',
|
||||
'queryString',
|
||||
],
|
||||
// swRegister: false,
|
||||
swCustom: path.resolve(__dirname, 'src/sw.js'),
|
||||
pwaHead: [
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
"display": "standalone",
|
||||
"scope": "./",
|
||||
"start_url": "./index.html",
|
||||
"related_applications": [
|
||||
{
|
||||
"platform": "webapp",
|
||||
"url": "https://v2.docusaurus.io/manifest.json"
|
||||
}
|
||||
],
|
||||
"icons": [
|
||||
{
|
||||
"src": "img/icons/icon-72x72.png",
|
||||
|
|
206
yarn.lock
206
yarn.lock
|
@ -20787,24 +20787,24 @@ wordwrap@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
|
||||
integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
|
||||
|
||||
workbox-background-sync@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.1.0.tgz#817de1ac1546fb6035759f151b0b4c5f0d3d9506"
|
||||
integrity sha512-A7YWWmAqzLkWYqqxzxoX4mciVjdSHpfX+JMADXoJ9SoLb6l/QReNJE+CNPew+gGPH6JLKNjZeecDmUpXFhzFPA==
|
||||
workbox-background-sync@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.1.1.tgz#db51214299b4be7a8aa274d8037f22d917241101"
|
||||
integrity sha512-w1b3j7snz4pQ8xp0i5Nci40qlglqdk70pbORBtMfl9uikI1qGjYfKq6oYeResCXYxb5mUYS245HsUclb6RFVJA==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-broadcast-update@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.1.0.tgz#63c1dc2d519aa6a7b9ce1db2f8da3e1db45b3422"
|
||||
integrity sha512-70G821I1Lb4Ex+rcjfKCbuFJ4WL4RSQsqvcByt/bLpPTTLoE6+VvLX3+1QtSK8P2+NmOsKkAqx9qiQkUdGbaYw==
|
||||
workbox-broadcast-update@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.1.1.tgz#5815749c9ad22ba4ef5184064a62fbdae3b04bf0"
|
||||
integrity sha512-8fBNOQt8ojWWtz3FbkDnKo8CpN6l8UjD2HpQr8tue7HJVfk0X1gfnzZLIDg7HCXhqF7ld3iQbGQqGPf1ihTY6A==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-build@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.1.0.tgz#e0ba4a0004da1079e934c7452c72c92ef7b52cba"
|
||||
integrity sha512-xJPqTEf+Pg9KAoTrNeVWpMjqi4cJIRn14i02bZjjbHsLNN38qrqc8xwAW48TwoPCYLjp104ST164/3RDgrc7yw==
|
||||
workbox-build@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.1.1.tgz#8333626fad45734d842293e6c2c1b725f4e15752"
|
||||
integrity sha512-mAI3dS4VnXri6BFg02arK1403SqHy2sOlzC4NVAk6Rl2+Ddxs+PmJO4cMTyHw0KEhQFcwk6V8cJeGiXJXYzinA==
|
||||
dependencies:
|
||||
"@babel/core" "^7.11.1"
|
||||
"@babel/preset-env" "^7.11.0"
|
||||
|
@ -20828,90 +20828,90 @@ workbox-build@^6.1.0:
|
|||
strip-comments "^2.0.1"
|
||||
tempy "^0.6.0"
|
||||
upath "^1.2.0"
|
||||
workbox-background-sync "^6.1.0"
|
||||
workbox-broadcast-update "^6.1.0"
|
||||
workbox-cacheable-response "^6.1.0"
|
||||
workbox-core "^6.1.0"
|
||||
workbox-expiration "^6.1.0"
|
||||
workbox-google-analytics "^6.1.0"
|
||||
workbox-navigation-preload "^6.1.0"
|
||||
workbox-precaching "^6.1.0"
|
||||
workbox-range-requests "^6.1.0"
|
||||
workbox-recipes "^6.1.0"
|
||||
workbox-routing "^6.1.0"
|
||||
workbox-strategies "^6.1.0"
|
||||
workbox-streams "^6.1.0"
|
||||
workbox-sw "^6.1.0"
|
||||
workbox-window "^6.1.0"
|
||||
workbox-background-sync "^6.1.1"
|
||||
workbox-broadcast-update "^6.1.1"
|
||||
workbox-cacheable-response "^6.1.1"
|
||||
workbox-core "^6.1.1"
|
||||
workbox-expiration "^6.1.1"
|
||||
workbox-google-analytics "^6.1.1"
|
||||
workbox-navigation-preload "^6.1.1"
|
||||
workbox-precaching "^6.1.1"
|
||||
workbox-range-requests "^6.1.1"
|
||||
workbox-recipes "^6.1.1"
|
||||
workbox-routing "^6.1.1"
|
||||
workbox-strategies "^6.1.1"
|
||||
workbox-streams "^6.1.1"
|
||||
workbox-sw "^6.1.1"
|
||||
workbox-window "^6.1.1"
|
||||
|
||||
workbox-cacheable-response@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.1.0.tgz#a99fdfe1507848486579df7b204c30e4cd0a74f2"
|
||||
integrity sha512-oDAi0vXHGaE5p9NOo4N180UTcEKm6t2JMgmlrq0PkEW2PZEu9YR/atSnCwzMW7xpDqpKWaQr/LGP4+eixS8gcA==
|
||||
workbox-cacheable-response@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.1.1.tgz#1dc71393cbce83559ad05a8ccb6c6fafa4cccc70"
|
||||
integrity sha512-jasNxelRrqCbzIAIMjHk7Ej9BOViBTQlvRJzv3Y0nYuWvxK0CDPQJSraGmTbu3LGiTBbrWEmxe1hVqvLyFKR9A==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-core@^5.1.4:
|
||||
version "5.1.4"
|
||||
resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-5.1.4.tgz#8bbfb2362ecdff30e25d123c82c79ac65d9264f4"
|
||||
integrity sha512-+4iRQan/1D8I81nR2L5vcbaaFskZC2CL17TLbvWVzQ4qiF/ytOGF6XeV54pVxAvKUtkLANhk8TyIUMtiMw2oDg==
|
||||
|
||||
workbox-core@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.1.0.tgz#2671b64f76550e83a4c2202676b67ce372e10881"
|
||||
integrity sha512-s3KqTJfBreO4xCZpR2LB5p/EknAx8eg0QumKiIgxM4hRO0RtwS2pJvTieNEM23X3RqxRhqweriLD8To19KUvjg==
|
||||
workbox-core@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.1.1.tgz#c8a9b424031b0cf7dacf9d7b8e023d126c9d0167"
|
||||
integrity sha512-xsc/72AQxFtt2BHmwU8QtnVV+W5ln4nnYGuz9Q5sPWYGqW4cH0P+FpZDoGM59bmNEyNf+W9bEmidW//e5GsbwQ==
|
||||
|
||||
workbox-expiration@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.1.0.tgz#cf6bb384e49d0c92b79233c46671d9c6d82478a2"
|
||||
integrity sha512-jp2xGk+LC4AhCoOxO/bC06GQkq/oVp0ZIf1zXLQh6OD2fWZPkXNjLLSuDnjXoGGPibYrq7gEE/xjAdYGjNWl1A==
|
||||
workbox-expiration@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.1.1.tgz#4468c3cdfe76b5888f4ae7e3aad63797a7bc24b1"
|
||||
integrity sha512-WbEv8NG1ZUiWI+jv3v7Jqed/PyCMoTpLcf3Nw7tKq0nGy6DFQtmSizO37uJ73oc8vttck97UBPQRiwyP1bZnAg==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-google-analytics@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.1.0.tgz#cd34100536250abc54070bcc23603213eb8e47e4"
|
||||
integrity sha512-BuUAJ747bMPC6IOKaQBXfotGybOfeHDRIC8ElF65ouB4O9kUJ3zh4EFxXmmJLgzTnji6265gXqNWcfuGiidk6A==
|
||||
workbox-google-analytics@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.1.1.tgz#c31876954779d65e1334c2dc3232e46d6a5f925a"
|
||||
integrity sha512-79PyeE4TyabGXqlDcRG2LKejs8yZ8OoU0/El0BwP8RGrZgp5GMDGuJkat4xggpRTVaOk8rb0aoSbVAYBWpa0pg==
|
||||
dependencies:
|
||||
workbox-background-sync "^6.1.0"
|
||||
workbox-core "^6.1.0"
|
||||
workbox-routing "^6.1.0"
|
||||
workbox-strategies "^6.1.0"
|
||||
workbox-background-sync "^6.1.1"
|
||||
workbox-core "^6.1.1"
|
||||
workbox-routing "^6.1.1"
|
||||
workbox-strategies "^6.1.1"
|
||||
|
||||
workbox-navigation-preload@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.1.0.tgz#e36d19f0d49ab5277e6c4e13b92f40da8955d62f"
|
||||
integrity sha512-N0c5Kmzu7lPKvirukbeZ3lN8KEAZU9xA4b1wmpV0VXUfRXVEk2ayXXqwHwMGFVi6FNCHiDLOcC8a2zW5kFLAeg==
|
||||
workbox-navigation-preload@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.1.1.tgz#3c7d39d5f102f4a76f24b48f97701b16ae56bd40"
|
||||
integrity sha512-vX5qJDk1Z663nuSSSHkcBFQQJwEe4UHynd5uoX3oC0IlecPclAbyT3QetVh0wYdXv6G6XD/LBd3iNZmlSbTosw==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-precaching@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.1.0.tgz#9ee3d28f27cd78daa62f5bd6a0d33f5682ac97a7"
|
||||
integrity sha512-zjye8MVzieBVJ3sS0hFcbKLp7pTHMfJM17YqxCxB0KykXWnxLOpYnStQ9M+bjWJsKJOQvbkPqvq5u9+mtA923g==
|
||||
workbox-precaching@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.1.1.tgz#f387ccdf60aab30228a4c7ed20a1cd8dee6aaaa4"
|
||||
integrity sha512-x8OKwtjd5ewe/x3VlKcXri1P3Tm0uV+uChdMYg/QryrCR9K8x9xwhAw8PZPkwrY0bLLsJMUoX9/lBu8DmjVqTA==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-routing "^6.1.0"
|
||||
workbox-strategies "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
workbox-routing "^6.1.1"
|
||||
workbox-strategies "^6.1.1"
|
||||
|
||||
workbox-range-requests@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.1.0.tgz#5fbe9edfbcdb97153ed5260575a54e53b0f85a2d"
|
||||
integrity sha512-BO025BdAvc6vTBXJfkfibcikMFLmLRECt0FrVrTiiQafdO3jWH9qX9zTdrjYf6GkiIjvejvvmSYegwU1mL6N3Q==
|
||||
workbox-range-requests@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.1.1.tgz#4e6d30e91cfc3855ff16cfa3df458e0487da2b4d"
|
||||
integrity sha512-ikZ0ZwbFAVMzJ08rM/spn9zC2tohGllFVii9R1q0+xMKvoGDsyzoQnoKrXgyUvcjRPn6ByFncAJ5lUKKG4TGkA==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-recipes@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.1.0.tgz#b925f2727ace05ce8762a1b6da6c0d749fd687ee"
|
||||
integrity sha512-r8YLtMtQnvfkK1htnfrrX1CxKHglZJiVlqnct9rYIU17n2LCalHdI0zQrPqzYdLLHZxTX25UpBsdib0cAATy0A==
|
||||
workbox-recipes@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.1.1.tgz#0cd1bd3b2ba223db563428ec5d17e960081f70d4"
|
||||
integrity sha512-GuzJXBQM+YaFxQwFvcRarAScUoRDoaWXKxxkLWHnCJf0H//MQ8zR9Ay1mv21N6iRoSH11S0u/4yxSeembG/fLA==
|
||||
dependencies:
|
||||
workbox-cacheable-response "^6.1.0"
|
||||
workbox-core "^6.1.0"
|
||||
workbox-expiration "^6.1.0"
|
||||
workbox-precaching "^6.1.0"
|
||||
workbox-routing "^6.1.0"
|
||||
workbox-strategies "^6.1.0"
|
||||
workbox-cacheable-response "^6.1.1"
|
||||
workbox-core "^6.1.1"
|
||||
workbox-expiration "^6.1.1"
|
||||
workbox-precaching "^6.1.1"
|
||||
workbox-routing "^6.1.1"
|
||||
workbox-strategies "^6.1.1"
|
||||
|
||||
workbox-routing@^5.0.0, workbox-routing@^5.1.4:
|
||||
version "5.1.4"
|
||||
|
@ -20920,12 +20920,12 @@ workbox-routing@^5.0.0, workbox-routing@^5.1.4:
|
|||
dependencies:
|
||||
workbox-core "^5.1.4"
|
||||
|
||||
workbox-routing@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.1.0.tgz#f885cb7801e2c9c5678f197656cf27a2b649c1d5"
|
||||
integrity sha512-FXQ5cwb6Mk90fC0rfQLX0pN+r/N4eBafwkh/QanJUq0e6jMPdDFLrlsikZL/0LcXEx+yAkWLytoiS+d2HOEBOw==
|
||||
workbox-routing@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.1.1.tgz#833ef6439905757241f9e4d56d8e282c20199c02"
|
||||
integrity sha512-Az3Gt3cHNK+W0gTfSb4eKGfwEap9Slak16Krr5SiLhE1gXUY2C2O123HucVCedXgIoqTLOXMtNj71Cm6SwYDEg==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-strategies@^5.0.0:
|
||||
version "5.1.4"
|
||||
|
@ -20935,32 +20935,32 @@ workbox-strategies@^5.0.0:
|
|||
workbox-core "^5.1.4"
|
||||
workbox-routing "^5.1.4"
|
||||
|
||||
workbox-strategies@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.1.0.tgz#9ddcee44408d2fb403f22a7989803b5c58560590"
|
||||
integrity sha512-HvUknzJdZWeV3x7Eq33a7TGAv9/r1TEiQK6kQ1QNzN+IKiqhIjnhKFHmMxb5hK1Gw9/aDSJTLNPDaLPfIJRQFQ==
|
||||
workbox-strategies@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.1.1.tgz#6e0adda84bcda17d3d0c48baec2eab9b988b9ca6"
|
||||
integrity sha512-7qYA9Eiq6hnP2dyenlD7ZtWI1ArBMT8yhTvHVlaOl9kYY7W+Iv3lAfRCjj/nucOKeVXATx4iVJEuFPn5J+8lzw==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
workbox-streams@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.1.0.tgz#2dbc78ddc863b47aa4fe399d9385d3ed8567e881"
|
||||
integrity sha512-V80OIfoIXaDkjWIGFSae5sBJuaG2r4bXk6HKpntBYaVQ72LD1CgkXRmZKmLJQ9ltHCx9Vmq/7+q1OF5mTKb8Qw==
|
||||
workbox-streams@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.1.1.tgz#0f204f070861eb1afccddeca4a5a8ba069596bd1"
|
||||
integrity sha512-EMhY+Y2O7+XVy8MFRmiDwKezAXLzbgjQOJDbxWaGKtwNPbwOF6gGZjCvmnNAU1K+MAvvUNsAFR6AAUKMSfOyaw==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-routing "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
workbox-routing "^6.1.1"
|
||||
|
||||
workbox-sw@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.1.0.tgz#dfaca1029264af71f13a90fdfb16cf8d64ed0537"
|
||||
integrity sha512-e2jnIWSmNrpO9Psy4D6euDdRUW8FTXAdMxOj5O02gxa01fri1kfTSM9irDnTGKUiSGc+hlycsvzGdr8bnvzDiA==
|
||||
workbox-sw@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.1.1.tgz#203ce4611309df1bf9c142d1e3b3a214b1b62944"
|
||||
integrity sha512-t6LLSx/rOS8d6w4+fsJOHDqGrjO89iBF0F8nBQgBleEPjvs9Be5j4B11y34Fw7s0CggeA3Kciutr4CqnQtPQUg==
|
||||
|
||||
workbox-window@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.1.0.tgz#5856127f183bcccfd93655b0e3cba5f2432b9156"
|
||||
integrity sha512-sjnE+nTSnrBvYx5KmpESvsTC82P3yy8h5l4Ae4Q8uLqdH29UQ3bMd8puGVVhX1JZFCmV40cvrbZ1fUj+3/TQ9g==
|
||||
workbox-window@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.1.1.tgz#c1d60f6a56b49235e36edc73c593fa470ffffc72"
|
||||
integrity sha512-ZT1enHgi6gYfm+HgRWq8nkqLFEtjOjkq3yGV/qhMmKvI39/sIdO4g2LcjqhnUjbhweedX+9KOOu3U4xasQpGcQ==
|
||||
dependencies:
|
||||
workbox-core "^6.1.0"
|
||||
workbox-core "^6.1.1"
|
||||
|
||||
worker-farm@^1.7.0:
|
||||
version "1.7.0"
|
||||
|
|
Loading…
Add table
Reference in a new issue