Angular 7 - Service Worker PWA + SSR 在服务器上无法工作

16

我正在努力让我的服务器端渲染和服务工作者在服务器端协作。

关于本地主机的信息 -> 工作正常

这正常工作。服务工作者可以工作并在每次更新时更新我的应用程序。此外,curl localhost:8082 会将我的信息返回给我。

我使用以下命令启动我的应用:npm run ssr

 "ssr": "npm run build:ssr && npm run serve:ssr",
 "build:ssr": "npm run build:client-and-server-bundles",
 "serve:ssr": "node dist/server.js",
 "build:client-and-server-bundles": "ng build --prod && npm run webpack:server",
 "webpack:server": "webpack --config webpack.server.config.js --progress --colors"

生产信息: -> 不可用

网站使用 HTTPS:https://airdropers.io,网站进程运行在一个关闭的端口上,并且具有 HAPROXY 将流量从 443 端口重定向到 web 服务器的端口。

网站服务器日志显示的问题:无法订阅通知 错误:服务工作者被禁用或此浏览器不支持

其他信息:

本地主机和生产环境下的 Node.js 版本相同:v9.0.0。 我使用以下过程构建生产环境:

  1. git pull
  2. npm run build:ssr
  3. pm2 start dist/server.js

更新于2019年2月23日

我现在有了更深入的理解。 我的问题是我使用 "node dist/server.js" 等 node 命令启动了我的 SSR/PWA 服务器。

据我了解,“node dist/server.js” 对于服务工作者(PWA)不起作用, 我引用了(https://angular.io/guide/service-worker-getting-started)中的一段话:

因为 ng serve 不支持服务工作者,你必须使用单独的 HTTP 服务器在本地测试项目。可以使用任何 HTTP 服务器。下面的示例使用 npm 中的 http-server 包。为了减少冲突的可能性并避免提供过时的内容,请在专用端口上进行测试并禁用缓存。

我无法使用http-server dist/browser 来启动它,因为这样会失去 SSR 的功能。

如何启动我的 PWA/SSR 服务器? 应该使用哪个命令? 应该构建哪个版本?

更新于2019年2月24日

正如 @Gökhan Kurt 提到的那样,服务工作程序与我的 SSR 服务器配合不完美。 我需要 SSR 来进行 SEO,并且我需要服务工作程序来进行浏览器推送通知。 有什么解决方案可以处理浏览器用户推送通知?像 One Signals 这样的第三方库吗?


欢迎提出任何想法和建议来帮助我解决这个问题。 感谢您的支持, Alex


听起来你需要对服务工作者的安装进行控制,以避免在节点环境中尝试注册。 - abraham
你是什么意思,@abraham?我非常乐意追随任何线索和想法。 - aorfevre
这可能是个愚蠢的问题...连接在 HTTPS 中是否需要端到端?反向代理终止 SSL? - jcuypers
我现在对我的问题有了更深入的理解。我现在会分享更新。 - aorfevre
@aorfevre,你能否提供SSR的完整解决方案以支持SEO和PWA?这将非常有帮助。我找不到其他解释这个的资源。 - Keyul
显示剩余2条评论
3个回答

16

实际上这与您的服务器没有关系。问题在于,服务工作者试图在服务器端进行注册,而这是不受支持的。您可以做的是使服务工作者在客户端进行注册。

我没有尝试过,但这可能适合您。您需要将单独的脚本放置在index.htmlbody的末尾以在浏览器上运行:

  <script>
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/ngsw-worker.js');
    }
  </script>

请注意,这只会给您提供服务工作者的基本缓存功能,并且可能无法为SwPushSwUpdate工作。您可以在此处查看服务工作者模块的内部工作方式。

还有一件事情是,服务工作者实际上不适用于SSR应用程序。生成的ngsw.json文件将不包括您所拥有的所有页面。您必须手动修改此文件或将其动态创建而非作为静态文件提供。

并且缓存所有页面并不是您想要做的事情(除非页面内容是静态的)。因为缓存的页面将始终显示相同的内容,因为您没有在客户端执行XHR请求。例如,如果主页已为客户端缓存,则该客户端将始终看到相同的页面,无论预期的动态内容如何。

此时,您应该考虑为什么同时需要SSR和Web APP。如果您需要SSR进行SEO,则不需要SW。当用户代理是爬行器时,只需进行SSR,并在客户端是普通用户时提供动态angular即可。

如何根据用户代理切换请求

这是我的想法,我不知道是否有人正在这样做。但从理论上讲,它应该可以工作。

首先,您将必须使用服务器端和客户端呈现配置将应用程序构建到两个不同的目录中(在我的示例中为DIST_FOLDER/ssrDIST_FOLDER/csr)。您可以从SSR中排除SW。您可以像往常一样在CSR中使用SW。

我发现这个软件包可以检测到爬虫/机器人用户代理。对于表达式和Angular,您将使用它如下:

app.get('*', (req, res) => {
  var CrawlerDetector = new Crawler(req)

  // check the current visitor's useragent
  if (CrawlerDetector.isCrawler())
  {
    // render the index html at server side
    res.render(path.join(DIST_FOLDER, 'ssr', 'index.html'), { req });
  }
  else {
    // serve static index.html file built without SSR and let the client render it
    res.sendFile(path.join(DIST_FOLDER, 'csr', 'index.html'));
  }
});
实施后,您可以通过将用户代理更改为此处所述的一种(即使用Postman)来调试应用程序,以查看其是否正常工作。

After implementing this, you can debug your application to see if it works correctly by changing your user agent to one that is written here (i.e. use Postman).


嗨,你的回答完全有道理,看起来这就是我的问题所在。我需要SSR来进行SEO优化,同时我也需要Service Worker来实现浏览器通知。你会如何建议我去做呢? - aorfevre
PS: 我将在几个小时内授予100美元的奖励;只是想引起您对我上一个问题的注意。 - aorfevre
@aorfevre,您可以同时使用同一台服务器。您提供的请求将会有条件地发生变化。如果您正在使用带缓存的CDN,则可能会出现问题,您可能需要使用两个服务器。否则,您可以同时使用同一台服务器。 - Gokhan Kurt
使用此软件包成功完成了任务:https://github.com/binarykitchen/spider-detector - aorfevre
1
谢谢,我的一天现在好多了 :) ,在经历了一周的紧张工作,将我们(庞大)的 Angular 网站转换为 SSR 后,这绝对是最好的解决方案。 - Elger Mensonides
显示剩余3条评论

1

通过一个小的“好用”的解决方案,#13351Angular 10 上运行良好,只需在 main.browser.ts 中做出很小的更改即可。

// Workaround for service worker, issue #13351.
document.addEventListener('DOMContentLoaded', () => {
  platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .then(() => {
      if ('serviceWorker' in navigator && environment.production) {
        navigator.serviceWorker.register('./ngsw-worker.js');
      }
    })
    .catch((err) => console.error(err));
});

ngsw-config.json文件中,我已将index编辑为引用index2.html而不是index.html。在我的情况下,这是必需的,以便在Firebase/NestJS上正确呈现SSR根路径(/)。

ngsw-config.json

{
  "$schema": "../../node_modules/@angular/service-worker/config/schema.json",      
  "index": "/index2.html",
  ...
}

当在Chrome DevTools中以prod标志运行时,可以在Application中看到Service Workers。通过View Page Source可以查看SSR。我还可以通过Chrome在我的桌面上安装应用程序。除此之外,该应用程序可以离线运行。无论是通过移动浏览器还是桌面应用程序都可以。

不知道为什么默认的移动通知,即Add to home screen没有弹出。


-1

当您将Angular PWA(服务工作者)添加到Angular SSR项目中时:

  • 请在ngsw-config.json文件中添加“navigationURLs:[]”

以下屏幕截图将在视图源上绑定SSR HTML。

enter image description here


这不是一个解决方案。因为如果您在ngsw-config.json文件中使用空的“navigationURLs”,那么将不会缓存任何内容。 - Kamran Taghaddos

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