Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix 'Uncaught (in promise) bad-precaching-response' error with service-worker + angular

With jhipster-6.2-generated project, I'm running into issues in turning my Spring + Angular app into a progressive web app (PWA). My service-worker successfully registers but will not provide offline functionality once my app is deployed to production. In my console, I get a bad-precaching-response, seemingly for at least one CSS file. With local deployments, caching works.

To successfully register my service-worker, I uncommented the serviceWorker-related code in index.html so that I have this:

    <script>
        if ('serviceWorker' in navigator) {
            window.addEventListener('load', function() {
                navigator.serviceWorker.register('/service-worker.js')
                    .then(function () {
                        console.log('Service Worker Registered');
                    });
            });
        }
    </script>

I generated my service worker successfully via the Workbox plugin:

new WorkboxPlugin.GenerateSW({
            clientsClaim: true,
            skipWaiting: true
        })

And I have my manifest.webapp in my webapp directory:

{
  "name": "<truncated>",
  "short_name": "<truncated>",
  "icons": [
        <truncated>
    ],
  "theme_color": "#000000",
  "background_color": "#e0e0e0",
  "start_url": ".",
  "display": "standalone",
  "orientation": "portrait"
}

With a local deployment, Workbox caches as expected. However, it fails in production.

When I deploy via Heroku, I force https. After first deploying after completing the above steps, I had to update my content security policy to include worker-src 'self' https://storage.googleapis.com/* blob:. While this took care of my initial security issues, I now have this error in my console with a live production deployment:

Uncaught (in promise) bad-precaching-response: 
bad-precaching-response :: [{"url":"https://<truncated>/swagger-ui/dist/css/typography.css?__WB_REVISION__=d41d8cd98f00b204e9800998ecf8427e",
"status":404}]

When I follow that link, I get to a page that is returning a 404 due to a CSP violation:

Refused to load the script 'https://linkhelp.clients.google.com/tbproxy/lh/wm?sourceid=wm&url=https%3A%2F%<truncated>.herokuapp.com%2Fswagger-ui%2Fdist%2Fcss%2Ftypography.css%3F&hl=en&site=<truncated>.herokuapp.com&error=http404&js=true' 
because it violates the following Content Security Policy directive: 
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com https://linkhelp.clients.google.com/* https://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js blob:". 
Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

I believe that the service-worker will NOT cache anything (for good reason) if there are any <400 responses from a url, which means my service-worker isn't working at all in production. However, despite whitelisting the linkhelp resource, the error still occurs. I fear that I went down a wrong path with adjusting security settings and might be missing something fundamental about service-workers, which I am new to.

I have consulted a number of guides I found by Googling some variation of jhipster pwa or the like but have ended up in the same place. These guides include:

  • Service-worker related tutorials at https://angular.io
  • https://blog.ippon.tech/build-a-pwa-in-jhipster/
  • https://developer.okta.com/blog/2017/05/09/progressive-web-applications-with-angular-and-spring-boot
  • https://www.smashingmagazine.com/2018/09/pwa-angular-6/

Expected result: Production deployment allows offline functionality the way local deployment does. Lighthouse audit succeeds.

Actual result: Prod deployment does NOT allow offline functionality. Lighthouse audit fails.

like image 303
kingofswords Avatar asked Sep 17 '19 18:09

kingofswords


Video Answer


1 Answers

Exclude swagger-ui from the workbox precache manifest by adding exclude: [/swagger-ui/] to the config in the call to WorkboxPlugin.GenerateSW in webpack/webpack.prod.js. Most users won't access that page so it's a good idea to exclude it from precaching.

new WorkboxPlugin.GenerateSW({
  clientsClaim: true,
  skipWaiting: true,
  exclude: [/swagger-ui/]
})

With that, the only thing missing from a perfect score is an apple-touch-icon

like image 60
Jon Ruddell Avatar answered Oct 02 '22 20:10

Jon Ruddell