Angular service worker with @angular/pwa package showing `HTTP error 504` when offline
Asked Answered
P

2

8

I am working on an angular PWA application. So I added an npm package by ng add @angular/pwa. It is added successfully with no errors.

The generated Manifest is working fine. But I am facing issues with the service worker. When the application goes online it stores all the caches (see attachment) but whenever the application goes offline, instead of serving the request from the service worker it shows the error - HTTP ERROR 504

Here is my ngsw-config.json -

   {
    "index": "/index.html",
    "assetGroups": [
      {
        "name": "app",
        "installMode": "prefetch",
        "resources": {
          "files": ["assets/images/favicon.ico", "/index.html", "/*.css", "/*.js"]
        }
      },
      {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**",
            "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
          ]
        }
      }
    ]
  }

Any help would be appreciable...

enter image description here

enter image description here

Purple answered 5/6, 2020 at 10:35 Comment(4)
I think you are doing everything ok. Based on http error (504), maybe your problem is related to where you are hosting your pwa. So, basically, your connection with the server is properly performed, but your server when it tries to serve your pwa does not found anything. In conclusion, the server is using a middleware of some kind (ex. nginx) and this is the reason why the browser is not deploying your cache because your browser established the connection and does not required the offline cache.Brunelle
Yes, This application is deployed on an Nginx server. Could you elaborate more on the issue?Purple
Ok, I'll do my best. Basically, there are two connection actually, the first one, is between your browser and the nginx proxy, this connection is properly performed, so your browser does not required to deploy the cache version. The problem is the second one, the connection is broken (because you are checking the offline feature). Maybe, to check if I am right, you can perform two fast test. Deploy in local and test the offline feature using your machine as server or shut down the nginx proxy and check it too.Brunelle
Ok Thank you so much @JTejedor, I will try your solution. :)Purple
B
7

As we commented, your problem is related with your web server or proxy nginx. Due you are connecting properly with nginx, the PWA offline feature is not enabled in your browser. After understanding what was your problem, I found several configuration that you would use in your nginx to allow a PWA proper behavior in offline case.

In google developers you can add these line in the nginx config file, to allow a PWA behavior:

location ~* (service-worker\.js)$ {
  # tells browsers the service worker scope
  add_header 'Service-Worker-Allowed' '/app';
}

Also I found this configuration file in the Philip Heltweg blog to allow the full behavior of a PWA.

server {
    listen 80;
    server_name _;

    gzip on;
    gzip_types text/html text/css application/javascript;

    root /var/www/;
    index index.html;

    # Force all paths to load either itself (js files) or go through index.html.
    location /index.html {
        try_files $uri /index.html;

        add_header Cache-Control "no-store, no-cache, must-revalidate";    
    }

    location / {
        try_files $uri /index.html;

        expires 1y;
        add_header Cache-Control "public";
    }
}

Well, finally, I found an interesting docker, If you are willing to use docker (of course), to run an nginx web server with the proper configuration in a simple way. Check this out.

I expect this three different approaches solve your problem. Let me know if I can help more!

Brunelle answered 12/6, 2020 at 16:25 Comment(1)
@Thank bro, I will check all of your solutions. and I will contact you if I need more help.Purple
A
15

Why error 504?

The 504 error doesn't come from your server, it comes from the service worker that is acting like a proxy.

Every HTTP request you make in your PWA passes through the service worker (SW), and two things may occur:

  • If the requested resource is on the SW cache, then it returns the content of the cache
  • If the requested resource is not on the SW cache, then the SW performs the request to the server

So if you are offline and the resource is not on the SW cache, then the SW will try to make the request to the server, but, as you are offline, that request will fail and the SW will return a 504 error. You can see that this is actually happening in the last image you posted: the http response at the top is the one you got from the SW with error 504 and the request below (see wheel icon at the left) is the one the SW performed to the server and failed.

Why cache mismatch?

Now, you may be wondering, why the SW doesn't find the resource in its cache?

Well, the Angular service worker is a great tool but it is very sensitive in a way that a minimum change will make it not work. The first thing you need to know is the caching mechanism it uses. Basically, when you build your Angular app, all the generated files have an associated hash that is computed with the content of each file (check the generated ngsw.json file). When your app is running, the SW compares this hash (computed at compilation time) with the hash of the requested resource (computed at runtime).

Many users report problems with this mechanism and some common reasons are:

  • Intermediate services (such as Cloudflare) that minify/uglify JS, CSS and HTML files
  • Automated scripts on a deployment pipeline that modify some files
  • FTP clients (such as FileZilla) that transfer files on text mode instead of binary mode (changing their encoding, line endings, etc)

All these produce changes on the file content and thus the SW will compute a different hash to the one computed on compilation time. This will cause a cache mismatch and your app won't work offline (you will get http 504 response).

Aditional information

Note that some users report that the app works offline sometimes or in some specific browsers. A possible explanation is that a browser-level cache mechanism is acting in these cases, instead of the SW cache itself.

To debug the Angular SW further, you can check its self-hosted debug page at /ngsw/state.

I recommend you to read the documentation of the Angular service worker and this discussion.

Alveolate answered 7/7, 2020 at 20:29 Comment(1)
I am facing similar issue with my angular application but users are online and some random users faced 504 gateway timeout error in API specially in login API and website keep continuously loading. error message like : http failure response for myapp.com/user/login: 504 Gateway timeout . I am not able to reproduce this issue so not able to find the root cause. I am not able to find logs in server access log for such errors.Frogman
B
7

As we commented, your problem is related with your web server or proxy nginx. Due you are connecting properly with nginx, the PWA offline feature is not enabled in your browser. After understanding what was your problem, I found several configuration that you would use in your nginx to allow a PWA proper behavior in offline case.

In google developers you can add these line in the nginx config file, to allow a PWA behavior:

location ~* (service-worker\.js)$ {
  # tells browsers the service worker scope
  add_header 'Service-Worker-Allowed' '/app';
}

Also I found this configuration file in the Philip Heltweg blog to allow the full behavior of a PWA.

server {
    listen 80;
    server_name _;

    gzip on;
    gzip_types text/html text/css application/javascript;

    root /var/www/;
    index index.html;

    # Force all paths to load either itself (js files) or go through index.html.
    location /index.html {
        try_files $uri /index.html;

        add_header Cache-Control "no-store, no-cache, must-revalidate";    
    }

    location / {
        try_files $uri /index.html;

        expires 1y;
        add_header Cache-Control "public";
    }
}

Well, finally, I found an interesting docker, If you are willing to use docker (of course), to run an nginx web server with the proper configuration in a simple way. Check this out.

I expect this three different approaches solve your problem. Let me know if I can help more!

Brunelle answered 12/6, 2020 at 16:25 Comment(1)
@Thank bro, I will check all of your solutions. and I will contact you if I need more help.Purple

© 2022 - 2024 — McMap. All rights reserved.