Skip to content

Commit

Permalink
fix(service-worker): change routing to allow redirect to login page (#…
Browse files Browse the repository at this point in the history
…669)

* fix(inject-manifest): skip index.html in second manifest

* refactor(pwa-app): reconfigure standalone option

* fix(service-worker): allow redirect to login page

* refactor: use String.prototype.endsWith
  • Loading branch information
KaiVandivier committed Oct 4, 2021
1 parent c99c736 commit 97c84d4
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 38 deletions.
5 changes: 3 additions & 2 deletions cli/src/lib/pwa/injectPrecacheManifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ module.exports = function injectPrecacheManifest(paths, config) {
swDest: paths.shellBuildServiceWorker,
globDirectory: paths.shellBuildOutput,
globPatterns: ['**/*'],
// Skip `static` directory; CRA's workbox-webpack-plugin handles it smartly
globIgnores: ['static/**/*'],
// Skip index.html and `static` directory;
// CRA's workbox-webpack-plugin handles it smartly
globIgnores: ['static/**/*', 'index.html'],
additionalManifestEntries: config.pwa.caching.additionalManifestEntries,
injectionPoint: 'self.__WB_BUILD_MANIFEST',
// Skip revision hashing for files with hash or semver in name:
Expand Down
2 changes: 0 additions & 2 deletions examples/pwa-app/d2.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const config = {
type: 'app',

standalone: true,

pwa: {
enabled: true,
caching: {
Expand Down
2 changes: 1 addition & 1 deletion examples/pwa-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test": "d2-app-scripts test",
"deploy": "d2-app-scripts deploy",
"serve": "serve -l 5500 build/app",
"demo": "yarn build --force --debug && yarn serve"
"demo": "yarn build --force --standalone --debug && yarn serve"
},
"peerDependencies": {
"@dhis2/app-runtime": "*",
Expand Down
100 changes: 67 additions & 33 deletions pwa/src/service-worker/service-worker.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { clientsClaim } from 'workbox-core'
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching'
import { precacheAndRoute, matchPrecache, precache } from 'workbox-precaching'
import { registerRoute, setDefaultHandler } from 'workbox-routing'
import {
NetworkFirst,
Expand Down Expand Up @@ -57,45 +57,79 @@ export function setUpServiceWorker() {
// Precache all of the assets generated by your build process.
// Their URLs are injected into the manifest variable below.
// This variable must be present somewhere in your service worker file,
// even if you decide not to use precaching. See https://cra.link/PWA
precacheAndRoute(self.__WB_MANIFEST || [])
// even if you decide not to use precaching. See https://cra.link/PWA.
// Includes all built assets and index.html
const precacheManifest = self.__WB_MANIFEST || []

// Extract index.html from the manifest to precache, then route
// in a custom way
const indexHtmlManifestEntry = precacheManifest.find(({ url }) =>
url.endsWith('index.html')
)
precache([indexHtmlManifestEntry])

// Custom strategy for handling app navigation, specifically to allow
// navigations to redirect to the login page while online if the
// user is unauthenticated. Fixes showing the app shell login dialog
// in production if a user is online and unauthenticated.
// Uses app-shell style routing to route navigations to index.html.
const navigationRouteMatcher = ({ request, url }) => {
// If this isn't a navigation, skip.
if (request.mode !== 'navigate') {
return false
}

// If this is a URL that starts with /_, skip.
if (url.pathname.startsWith('/_')) {
return false
}

// If this looks like a URL for a resource, because it contains
// a file extension, skip (unless it's index.html)
if (
fileExtensionRegexp.test(url.pathname) &&
!url.pathname.endsWith('index.html')
) {
return false
}

// Return true to signal that we want to use the handler.
return true
}
const indexUrl = process.env.PUBLIC_URL + '/index.html'
const navigationRouteHandler = ({ request }) => {
return fetch(request)
.then(response => {
if (response.type === 'opaqueredirect') {
// It's sending a redirect to the login page. Return
// that to the client
return response
}

// Otherwise return precached index.html
return matchPrecache(indexUrl)
})
.catch(() => {
// Request failed (maybe offline). Return cached response
return matchPrecache(indexUrl)
})
}
registerRoute(navigationRouteMatcher, navigationRouteHandler)

// Handle the rest of files in the manifest
const restOfManifest = precacheManifest.filter(
e => e !== indexHtmlManifestEntry
)
precacheAndRoute(restOfManifest)

// Similar to above; manifest injection from `workbox-build`
// Precaches all assets in the shell's build folder except in `static`
// (which CRA's workbox-webpack-plugin handle smartly).
// Additional files to precache can be added using the
// `additionalManifestEntries` option in d2.config.js; see the docs
// `additionalManifestEntries` option in d2.config.js; see the docs and
// 'injectPrecacheManifest.js' in the CLI package.
// '[]' fallback prevents an error when switching pwa enabled to disabled
precacheAndRoute(self.__WB_BUILD_MANIFEST || [])

// From CRA Boilerplate:
// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developers.google.com/web/fundamentals/architecture/app-shell
registerRoute(
// Return false to exempt requests from being fulfilled by index.html.
({ request, url }) => {
// If this isn't a navigation, skip.
if (request.mode !== 'navigate') {
return false
}

// If this is a URL that starts with /_, skip.
if (url.pathname.startsWith('/_')) {
return false
}

// If this looks like a URL for a resource, because it contains
// a file extension, skip.
if (url.pathname.match(fileExtensionRegexp)) {
return false
}

// Return true to signal that we want to use the handler.
return true
},
createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html')
)
}

// Request handler during recording mode: ALL requests are cached
Expand Down

0 comments on commit 97c84d4

Please sign in to comment.