Angular 带有@angular/pwa 包的服务工作者在离线时显示“HTTP 错误 504”
Angular service worker with @angular/pwa package showing `HTTP error 504` when offline
我正在开发 angular PWA 应用程序。所以我通过 ng add @angular/pwa
添加了一个 npm 包。添加成功,没有错误。
生成的清单工作正常。但我面临服务工作者的问题。当应用程序上线时,它会存储所有缓存(见附件),但每当应用程序下线时,它不会为来自 service worker 的请求提供服务,而是显示错误 - 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)"
]
}
}
]
}
任何帮助将不胜感激...
正如我们评论的那样,您的问题与您的网络服务器或代理 nginx 有关。由于您与 nginx 连接正常,因此您的浏览器未启用 PWA 离线功能。在了解你的问题是什么之后,我发现了几个你会在你的 nginx 中使用的配置,以允许 PWA 在离线情况下的正确行为。
在 google developers 中,您可以在 nginx 配置文件中添加这些行,以允许 PWA 行为:
location ~* (service-worker\.js)$ {
# tells browsers the service worker scope
add_header 'Service-Worker-Allowed' '/app';
}
我还在 the Philip Heltweg blog 中找到了这个配置文件以允许 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服务器一个简单的方法。 Check this out.
我希望这三种不同的方法能解决您的问题。如果我能提供更多帮助,请告诉我!
为什么错误 504?
504 错误不是来自您的服务器,它来自充当代理的服务工作者。
您在 PWA 中发出的每个 HTTP 请求都会通过服务工作者 (SW),并且可能会发生两件事:
- 如果请求的资源在 SW 缓存中,那么它return就是缓存的内容
- 如果请求的资源不在SW缓存中,则SW向服务器执行请求
因此,如果您处于离线状态且资源不在 SW 缓存中,则 SW 将尝试向服务器发出请求,但是,由于您处于离线状态,该请求将失败并且 SW 将 return 504 错误。您可以看到这实际上发生在您发布的最后一张图片中:顶部的 http 响应是您从 SW 获得的错误 504,下面的请求(请参见左侧的轮子图标)是 SW 执行的请求到服务器并失败。
为什么缓存不匹配?
现在,您可能想知道,为什么 SW 在其缓存中找不到资源?
好吧,Angular service worker 是一个很棒的工具,但它非常敏感,最小的更改就会使其无法工作。您首先需要知道的是它使用的缓存机制。基本上,当您构建 Angular 应用程序时,所有生成的文件都有一个关联的哈希值,该哈希值是根据每个文件的内容计算的(检查生成的 ngsw.json
文件)。当您的应用程序是 运行 时,SW 会将此哈希值(在编译时计算)与所请求资源的哈希值(在运行时计算)进行比较。
许多用户报告此机制存在问题,一些常见原因是:
- minify/uglify JS、CSS 和 HTML 文件的中间服务(例如 Cloudflare)
- 修改某些文件的部署管道上的自动化脚本
- FTP 以文本模式而不是二进制模式传输文件的客户端(例如 FileZilla)(更改其编码、行尾等)
所有这些都会对文件内容产生变化,因此 SW 将计算与编译时计算的哈希值不同的哈希值。这将导致缓存不匹配,您的应用将无法离线运行(您将收到 http 504 响应)。
附加信息
请注意,一些用户报告说该应用程序 有时 或在某些特定浏览器中离线工作。一种可能的解释是,在这些情况下,浏览器级缓存机制起作用,而不是 SW 缓存本身。
要进一步 debug the Angular SW,您可以在 /ngsw/state
查看其自托管调试页面。
我建议您阅读 documentation of the Angular service worker and this discussion。
我正在开发 angular PWA 应用程序。所以我通过 ng add @angular/pwa
添加了一个 npm 包。添加成功,没有错误。
生成的清单工作正常。但我面临服务工作者的问题。当应用程序上线时,它会存储所有缓存(见附件),但每当应用程序下线时,它不会为来自 service worker 的请求提供服务,而是显示错误 - 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)"
]
}
}
]
}
任何帮助将不胜感激...
正如我们评论的那样,您的问题与您的网络服务器或代理 nginx 有关。由于您与 nginx 连接正常,因此您的浏览器未启用 PWA 离线功能。在了解你的问题是什么之后,我发现了几个你会在你的 nginx 中使用的配置,以允许 PWA 在离线情况下的正确行为。
在 google developers 中,您可以在 nginx 配置文件中添加这些行,以允许 PWA 行为:
location ~* (service-worker\.js)$ {
# tells browsers the service worker scope
add_header 'Service-Worker-Allowed' '/app';
}
我还在 the Philip Heltweg blog 中找到了这个配置文件以允许 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服务器一个简单的方法。 Check this out.
我希望这三种不同的方法能解决您的问题。如果我能提供更多帮助,请告诉我!
为什么错误 504?
504 错误不是来自您的服务器,它来自充当代理的服务工作者。
您在 PWA 中发出的每个 HTTP 请求都会通过服务工作者 (SW),并且可能会发生两件事:
- 如果请求的资源在 SW 缓存中,那么它return就是缓存的内容
- 如果请求的资源不在SW缓存中,则SW向服务器执行请求
因此,如果您处于离线状态且资源不在 SW 缓存中,则 SW 将尝试向服务器发出请求,但是,由于您处于离线状态,该请求将失败并且 SW 将 return 504 错误。您可以看到这实际上发生在您发布的最后一张图片中:顶部的 http 响应是您从 SW 获得的错误 504,下面的请求(请参见左侧的轮子图标)是 SW 执行的请求到服务器并失败。
为什么缓存不匹配?
现在,您可能想知道,为什么 SW 在其缓存中找不到资源?
好吧,Angular service worker 是一个很棒的工具,但它非常敏感,最小的更改就会使其无法工作。您首先需要知道的是它使用的缓存机制。基本上,当您构建 Angular 应用程序时,所有生成的文件都有一个关联的哈希值,该哈希值是根据每个文件的内容计算的(检查生成的 ngsw.json
文件)。当您的应用程序是 运行 时,SW 会将此哈希值(在编译时计算)与所请求资源的哈希值(在运行时计算)进行比较。
许多用户报告此机制存在问题,一些常见原因是:
- minify/uglify JS、CSS 和 HTML 文件的中间服务(例如 Cloudflare)
- 修改某些文件的部署管道上的自动化脚本
- FTP 以文本模式而不是二进制模式传输文件的客户端(例如 FileZilla)(更改其编码、行尾等)
所有这些都会对文件内容产生变化,因此 SW 将计算与编译时计算的哈希值不同的哈希值。这将导致缓存不匹配,您的应用将无法离线运行(您将收到 http 504 响应)。
附加信息
请注意,一些用户报告说该应用程序 有时 或在某些特定浏览器中离线工作。一种可能的解释是,在这些情况下,浏览器级缓存机制起作用,而不是 SW 缓存本身。
要进一步 debug the Angular SW,您可以在 /ngsw/state
查看其自托管调试页面。
我建议您阅读 documentation of the Angular service worker and this discussion。