Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: catch sw precaching errors [DHIS2-15625] #812

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cli/src/lib/pwa/compileServiceWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ function compileServiceWorker({ config, paths, mode }) {
// TODO: This could be cleaner if the production SW is built in the same
// way instead of using the CRA webpack config, so both can more easily
// share environment variables.
const env = getEnv({ name: config.title, ...getPWAEnvVars(config) })
const env = getEnv({
name: config.title,
version: config.version,
...getPWAEnvVars(config),
})

const webpackConfig = {
mode, // "production" or "development"
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"@dhis2/cli-style": "^10.4.3",
"@dhis2/cli-utils-docsite": "^3.0.0",
"concurrently": "^6.0.0",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"serve": "^12.0.0"
},
"scripts": {
Expand All @@ -37,7 +39,8 @@
"docs:build": "d2-utils-docsite build ./docs -o ./dist",
"test:adapter": "yarn workspace @dhis2/app-adapter test",
"test:cli": "yarn workspace @dhis2/cli-app-scripts test",
"test": "yarn test:adapter && yarn test:cli"
"test": "yarn test:adapter && yarn test:cli",
"postinstall": "patch-package"
},
"d2": {
"docsite": {
Expand Down
57 changes: 57 additions & 0 deletions patches/workbox-precaching+6.5.3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
diff --git a/node_modules/workbox-precaching/PrecacheController.js b/node_modules/workbox-precaching/PrecacheController.js
index e00975e..b728b6a 100644
--- a/node_modules/workbox-precaching/PrecacheController.js
+++ b/node_modules/workbox-precaching/PrecacheController.js
@@ -150,6 +150,7 @@ class PrecacheController {
return waitUntil(event, async () => {
const installReportPlugin = new PrecacheInstallReportPlugin();
this.strategy.plugins.push(installReportPlugin);
+ const failedUrls = []
// Cache entries one at a time.
// See https://github.com/GoogleChrome/workbox/issues/2528
for (const [url, cacheKey] of this._urlsToCacheKeys) {
@@ -164,12 +165,43 @@ class PrecacheController {
params: { cacheKey },
request,
event,
- }));
+ }))
+ // DHIS2: Catch precaching errors to provide a more thorough
+ // error message
+ .catch(err => {
+ failedUrls.push(url)
+ console.error(`Error when attempting to fetch and cache URL ${url}:\n`, err)
+ });
}
const { updatedURLs, notUpdatedURLs } = installReportPlugin;
if (process.env.NODE_ENV !== 'production') {
printInstallDetails(updatedURLs, notUpdatedURLs);
}
+ // DHIS2: Log failed requests to give clear feedback, and throw
+ // error to abort installation
+ if (failedUrls.length > 0) {
+ const appVersion = process.env.REACT_APP_DHIS2_APP_VERSION
+ const appName = process.env.REACT_APP_DHIS2_APP_NAME
+ const errorMessage =
+ `The following assets were unable to be precached when ` +
+ `attempting to install ${appName} version ${appVersion}, ` +
+ `so the installation has been aborted:\n` +
+ `${failedUrls.reduce((acc, curr) => acc + ` * ${curr}\n`, '')}\n` +
+ `If another version of the app is installed in the browser, ` +
+ `you will continue to see that version. If not, you will ` +
+ `see version ${appVersion}, but caching and offline ` +
+ `features will be unavailable, and the app may not be ` +
+ `fully functional due to the missing files. You can find ` +
+ `the app version that's currently active at the bottom ` +
+ `of the user profile menu.\n\n` +
+ `[FOR TECHNICAL USERS]: If another version is installed ` +
+ `and you would like to attempt to view version ` +
+ `${appVersion} (knowing the above caveats), you may use ` +
+ `your browser's developer tools to find the service worker ` +
+ `that's currently active for this app and unregister it.`
+ throw new Error(errorMessage)
+ }
+
return { updatedURLs, notUpdatedURLs };
});
}
79 changes: 77 additions & 2 deletions pwa/src/service-worker/set-up-service-worker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { precacheAndRoute, matchPrecache, precache } from 'workbox-precaching'
import {
precacheAndRoute,
matchPrecache,
precache,
// PrecacheController,
// PrecacheRoute,
} from 'workbox-precaching'
import { registerRoute, setDefaultHandler } from 'workbox-routing'
import {
NetworkFirst,
Expand Down Expand Up @@ -42,7 +48,7 @@ export function setUpServiceWorker() {

// Disable verbose logs
// TODO: control with env var
self.__WB_DISABLE_DEV_LOGS = true
// self.__WB_DISABLE_DEV_LOGS = true

// Globals (Note: global state resets each time SW goes idle)

Expand Down Expand Up @@ -155,6 +161,75 @@ export function setUpServiceWorker() {
// '[]' fallback prevents an error when switching pwa enabled to disabled
const sharedBuildManifest = self.__WB_BUILD_MANIFEST || []
precacheAndRoute(sharedBuildManifest)
} else {
// This will execute in dev environments
precacheAndRoute([
// Let this one work
{ url: './index.html', revision: '1' },
// The following are expected to fail
{ url: 'https://not-a-site.com/hey.jpg', revision: '1' },
{ url: 'https://not-a-site.com/bogus1.jpg', revision: '1' },
{ url: 'https://not-a-site.com/derp2.jpg', revision: '1' },
{ url: 'https://not-a-site.com/diddlibap3.jpg', revision: '1' },
{ url: 'https://not-a-site.com/squip4.jpg', revision: '1' },
])

/* An alternative to patch package, where a custom precache controller is made and implemented
class CustomPrecacheController extends PrecacheController {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is included here to show an example of another approach to catching & handling precaching errors (option 2 in the main PR comment)

// Copied and modified slightly from the original `install` method
// in order to catch errors without scrapping the entire SW
// installation
install(event) {
const fetchAndCache = async () => {
// Cache entries one at a time.
// See https://github.com/GoogleChrome/workbox/issues/2528
for (const [url, cacheKey] of this._urlsToCacheKeys) {
const integrity =
this._cacheKeysToIntegrities.get(cacheKey)
const cacheMode = this._urlsToCacheModes.get(url)

const request = new Request(url, {
integrity,
cache: cacheMode,
credentials: 'same-origin',
})

await Promise.all(
this.strategy.handleAll({
params: { cacheKey },
request,
event,
})
).catch((err) => {
console.log('Whoops there was a precaching err!')
console.error(err)
})
}
}
event.waitUntil(fetchAndCache())
}
}
const precacheController = new CustomPrecacheController()

precacheController.addToCacheList([
{ url: 'https://not-a-site.com/index.html', revision: '5' },
{ url: 'https://not-a-site.com/hey.jpg', revision: '1000' },
{ url: 'https://not-a-site.com/bogus1.jpg', revision: '1000' },
{ url: 'https://not-a-site.com/derp2.jpg', revision: '1000' },
{ url: 'https://not-a-site.com/diddlibap3.jpg', revision: '1000' },
{ url: 'https://not-a-site.com/squip4.jpg', revision: '1000' },
])

self.addEventListener('install', (event) => {
precacheController.install(event)
})

self.addEventListener('activate', (event) => {
precacheController.activate(event)
})

const precacheRoute = new PrecacheRoute(precacheController)
registerRoute(precacheRoute) */
}

// Handling pings: only use the network, and don't update the connection
Expand Down
83 changes: 82 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5052,6 +5052,11 @@ ci-info@^3.2.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128"
integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==

ci-info@^3.7.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91"
integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==

cjs-module-lexer@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
Expand Down Expand Up @@ -7423,6 +7428,13 @@ find-up@^5.0.0:
locate-path "^6.0.0"
path-exists "^4.0.0"

find-yarn-workspace-root@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
dependencies:
micromatch "^4.0.2"

flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
Expand Down Expand Up @@ -9584,6 +9596,13 @@ json-stable-stringify-without-jsonify@^1.0.1:
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==

json-stable-stringify@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0"
integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==
dependencies:
jsonify "^0.0.1"

json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
Expand Down Expand Up @@ -9617,6 +9636,11 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"

jsonify@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==

jsonparse@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
Expand Down Expand Up @@ -9676,6 +9700,13 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==

klaw-sync@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c"
integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==
dependencies:
graceful-fs "^4.1.11"

klaw@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/klaw/-/klaw-4.0.1.tgz#8dc6f5723f05894e8e931b516a8ff15c2976d368"
Expand Down Expand Up @@ -10831,7 +10862,7 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"

open@^7.3.1:
open@^7.3.1, open@^7.4.2:
version "7.4.2"
resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321"
integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
Expand Down Expand Up @@ -11070,6 +11101,27 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==

patch-package@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61"
integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
chalk "^4.1.2"
ci-info "^3.7.0"
cross-spawn "^7.0.3"
find-yarn-workspace-root "^2.0.0"
fs-extra "^9.0.0"
json-stable-stringify "^1.0.2"
klaw-sync "^6.0.0"
minimist "^1.2.6"
open "^7.4.2"
rimraf "^2.6.3"
semver "^7.5.3"
slash "^2.0.0"
tmp "^0.0.33"
yaml "^2.2.2"

path-dirname@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
Expand Down Expand Up @@ -11778,6 +11830,11 @@ postcss@^8.4.14, postcss@^8.4.4, postcss@^8.4.7:
picocolors "^1.0.0"
source-map-js "^1.0.2"

postinstall-postinstall@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3"
integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==

prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
Expand Down Expand Up @@ -12696,6 +12753,13 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
dependencies:
glob "^7.1.3"

rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
dependencies:
glob "^7.1.3"

rimraf@~2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
Expand Down Expand Up @@ -12903,6 +12967,13 @@ semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7:
dependencies:
lru-cache "^6.0.0"

semver@^7.5.3:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"

send@0.18.0, send@latest:
version "0.18.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
Expand Down Expand Up @@ -13068,6 +13139,11 @@ sisteransi@^1.0.5:
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==

slash@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==

slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
Expand Down Expand Up @@ -15315,6 +15391,11 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==

yaml@^2.2.2:
version "2.3.1"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==

yargs-parser@^13.1.2:
version "13.1.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
Expand Down
Loading