使用@angular/pwa包的Angular服务工作者在离线时显示`HTTP错误504`。

7

我正在开发一个基于Angular的PWA应用程序。因此,我通过 ng add @angular/pwa 添加了一个npm包。添加成功,没有出现任何错误。

生成的清单(Manifest)运行良好。但是,我在服务工作者方面遇到了问题。当应用程序联机时,它会存储所有缓存(请参见附件),但是每当应用程序离线时,它不会从服务工作者处提供请求,而是显示错误 - HTTP ERROR 504

这是我的 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)"
          ]
        }
      }
    ]
  }

任何帮助都将受到赞赏...

在这里输入图片描述

在这里输入图片描述


1
我认为你做得很好。根据http错误(504),也许你的问题与你托管PWA的位置有关。因此,基本上,你与服务器的连接是正确的,但当服务器尝试提供你的PWA时找不到任何内容。总之,服务器正在使用某种中间件(例如nginx),这就是为什么浏览器没有部署你的缓存,因为你的浏览器建立了连接并不需要离线缓存的原因。 - JTejedor
是的,这个应用程序部署在一个Nginx服务器上。您能详细说明一下问题吗? - Alok Mali
1
好的,我会尽力而为。基本上,实际上有两个连接,第一个是您的浏览器和nginx代理之间的连接,这个连接已经正确执行,因此您的浏览器不需要部署缓存版本。问题在于第二个连接断开了(因为您正在检查离线功能)。也许,为了检查我是否正确,您可以执行两个快速测试。在本地部署并使用您的计算机作为服务器测试离线功能,或关闭nginx代理并进行检查。 - JTejedor
好的,非常感谢@JTejedor,我会尝试您的解决方案。 :) - Alok Mali
2个回答

14

为什么会出现504错误?

504错误不是来自于你的服务器,而是由充当代理的服务工作者(Service Worker)引起的。

在你的PWA中,每个HTTP请求都会经过服务工作者(SW),并且可能发生以下两种情况:

  • 如果所请求的资源在SW缓存中,则返回缓存内容
  • 如果所请求的资源不在SW缓存中,则SW将向服务器执行请求

因此,如果你处于离线状态且所请求的资源不在SW缓存中,则SW将尝试向服务器发送请求,但由于你处于离线状态,该请求将失败,并且SW将返回一个504错误。你可以看到这实际上正在最后一张你发布的图片中发生:顶部的http响应是你从SW获取的带有错误504的响应,下面的请求(见左侧的轮子图标)是SW执行到服务器并失败的请求。

为什么会出现缓存不匹配的情况?

现在,你可能会想知道,为什么SW在其缓存中找不到该资源?

好吧,Angular服务工作者是一个很棒的工具,但它在某种程度上非常敏感,即最小的更改都会使其无法正常工作。你需要知道的第一件事是它使用的缓存机制。基本上,当你构建Angular应用程序时,所有生成的文件都有一个关联的哈希值,该哈希值是通过每个文件的内容计算得出的(检查生成的ngsw.json文件)。当你的应用程序运行时,SW将此哈希值(在编译时计算)与所请求资源的哈希值(在运行时计算)进行比较。

许多用户报告了这种机制存在的问题,一些常见原因包括:

  • 中间服务(如Cloudflare),会对JS、CSS和HTML文件进行缩小/混淆
  • 部署管道上的自动化脚本修改了某些文件
  • FTP客户端(如FileZilla)以文本模式而不是二进制模式传输文件(更改其编码、换行符等)

所有这些都会对文件内容产生更改,因此SW将计算出与编译时计算的哈希值不同的哈希值。这将导致缓存不匹配,并且你的应用程序无法离线工作(你将收到http 504响应)。

附加信息

请注意,一些用户报告称应用程序有时可以在离线状态下工作或在某些特定的浏览器中工作。一个可能的解释是,在这些情况下,浏览器级别的缓存机制正在起作用,而不是SW缓存本身。

要进一步调试Angular SW,可以在/ngsw/state上检查其自托管的调试页面。

我建议您阅读Angular服务工作者文档这个讨论

5
我们之前提到,你的问题与你的Web服务器或代理nginx有关。由于你已经正常连接了nginx,因此浏览器中未启用PWA离线功能。在了解了你的问题后,我发现几个需要在nginx中配置的设置,以便在离线情况下使PWA正常运作。
谷歌开发者网站中,您可以将以下行添加到nginx配置文件中,以允许PWA正常工作:
location ~* (service-worker\.js)$ {
  # tells browsers the service worker scope
  add_header 'Service-Worker-Allowed' '/app';
}

我在Philip Heltweg的博客中找到了这个配置文件,可以允许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";
    }
}

好了,终于找到了一个有趣的Docker,如果你愿意使用Docker(当然),可以以简单的方式运行带有正确配置的Nginx Web服务器。看看这个

我期望这三种不同的方法可以解决你的问题。如果需要更多帮助,请告诉我!


@谢谢兄弟,我会检查你的所有解决方案。如果需要更多帮助,我会联系你的。 - Alok Mali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接