32

在以前版本的 Angular 服务工作者实现中,配置选项之一是"routing". 这可以在这个未回答的 SO 问题中看到,在这个Angular CLI 问题中被引用,剩下的最好的文档似乎是Stephen Fluin(在 Angular 团队中)的博客文章,以及来自 Alex Rickabaugh的I/O 演讲(来自谷歌)。

使用 Angular 5,ServiceWorkerModule已经很好地构建了,现在可以使用该ngsw-config.json文件处理大部分配置。但是,在angular.io 指南文档中的任何地方,都不再提及如何处理路由重定向。所以我最终遇到了以下问题:当我访问了我的应用程序并离线时,我直接访问它时仍然可以访问该应用程序:https ://jackkoppa.github.io/cityaq-sw-issue 。但是,在加载应用程序时会重定向到search路由,大多数用户会尝试从https://jackkoppa.github.io/cityaq-sw-issue/search?cities=Shanghai之类的 URL 加载(为简单起见,我现在只谈论 Chrome 桌面和移动设备,并尽可能使用隐身模式)。

当您尝试在离线时访问该 URL 时,您会立即收到 504 - Gateway Timeout。发生这种情况是因为 service worker 只缓存了索引,并且不知道其他路由应该重定向到索引以便它可以加载。我相信 Angular 服务工作者实现的先前迭代可以通过设置重定向到给定路由的索引来处理这种情况。有没有办法在当前的 Angular 5+ngsw-config.json或生成的ngsw.json文件中处理这个重定向?除此之外,应该如何在单独的服务工作者 JS 文件中处理解决方法?

4

2 回答 2

9

TL;DR:我已经确定了至少两个导致我的案例损坏的问题;您现在可以使用此构建脚本来尝试我的修复,并在此处查看应用程序脱机工作。需要进一步的测试和拉取请求。


虽然我一直无法找到有据可查的答案,但这是我迄今为止在单步执行ngsw-worker.js文件以及阅读@angular/service-worker提交历史时能够找到的内容。

“路由”的新ServiceWorkerModule方法是接受任何“导航”请求(即同一域上的非索引路由),然后重新运行该handleFetch方法,但现在指向index.html请求(source)。这应该可以正常工作,因为一旦 SPA 检索到索引的缓存文件,它应该能够重定向到 URL。

所以导致我上面的站点在离线时失败的问题一定与路由没有直接关系,到目前为止我已经找到了 2 个。通过变通方法更正这些问题使我的应用程序大部分按预期工作。随着原始问题中的复制步骤,cityaq现在正在工作,而我已经在cityaq-sw-issue复制了原始的失败站点。

问题:

  1. 从 CLI 设置标志的 Angular 应用程序的托管版本会--base-href列出其服务工作者资源的绝对 URL。在将请求与这些资源进行比较时,ngsw-worker.js需要相对 URL

    • 资源
    • 我相当有信心这个问题需要解决,并且我将通过拉取请求来解决它。发生这种情况是因为生成baseHref时包含在资源 URLngsw.json中(
  2. ngsw-worker.js根据我的经验,在3 个可用的“状态”中,EXISTING_CLIENTS_ONLY似乎赌注设置不正确。

    • 来源 1 ,来源 2
    • 我对这种变化不太有信心,因为我无法始终如一地看到导致这种状态的原因。但是,如果 & 当服务工作者进入此状态时,ngsw-worker.js将不再尝试检索缓存的资源(source),并且在我的测试中似乎是“正确”的情况下,即使唯一的更改是,应用程序仍会进入此状态删除互联网连接

虽然我为问题 #1 整理了一个 PR,并等待一些帮助理解问题 #2,但我正在使用解决方法构建脚本ngsw-worker.js在它生成后进行修改。警告:这很丑陋,并且肯定会修改设置的预期“安全”行为EXISTING_CLIENTS_ONLY。但是,对于我的应用程序,它在本地运行http-server

要使用解决方法: (Angular 5,使用 Angular 5.2.1 测试)

  1. npm install replace-in-file --save-dev
  2. 将此脚本包含在您的应用程序中,例如在build/fix-sw.js
  3. 在你的package.json
"scripts": {
   ...
   "sw-build": "ng build --prod && node build/fix-sw",
   "sw-build-live": ng build --prod --base-href https://your-url.com/ && node build/fix-sw"
   ...
}
  1. 在本地运行

npm 运行 sw-build
光盘区
http服务器-p 8080

  1. 并在发送到服务器之前为您的实时 URL 准备构建(例如使用angular-cli-ghpages

npm 运行 sw-build-live

于 2018-02-11T15:09:37.613 回答
0

我只需要处理几天,虽然我没有使用路由,只是一个非根基础href。我将分享对我有用的配置,它至少有机会为路由应用程序工作,因为每当我尝试使用route/ngsw/state调试时,我都会得到我的应用程序。

  1. 这是主站点之外的“子应用程序”,并直接链接到http(s)://<host>/route/index.html
  2. manifest.webmanifest 刚刚被提供,所以不知道也不关心 Angular 对事物做了什么,所以它是明确的,包括子路线。
    "scope": "/route/",
    "start_url": "/route/index.html",
    
  3. angular.json 设置了 baseHref,因为整个应用程序都在此下提供,这就是 base-href 的用途:
    "baseHref": "/route/",
    
  4. ngsw-config.json 是一个棘手的问题,因为它使用其模式在部署文件夹中查找文件以添加到 ngsw.json,因此在此处添加 baseHref 或使用相对路径之类的操作会破坏它。该文件需要考虑并看起来像是从根目录提供的,例如:
    "index": "/index.html",
    ...
      "files": [
        "/index.html",
        "/*.js"
      ]
    
  5. Angular CLI 将在 ngsw.json 中添加 baseHref,为您提供资产 URL 和哈希键,例如"/route/index.html"
  6. 您的应用程序将发出类似于 baseHref 的请求"/route/index.html""/route/main.js"因为 baseHref 与它们在其下进行散列并且现在实际缓存的键相匹配。
  7. Service Worker 已在 下正确注册/route/,因此它将 a.) 尝试处理请求并 b.) 当您离线时在其缓存中找到它们。

让这件事变得如此困难的一件事是有多少种不同的方法来指定路径和基础,并且有些方法非常适应,而另一些则非常严格。如果你的部署被破坏了,你就不能真正使用内置的调试,也不能像使用一个健全的模块一样打开调试日志。文档非常稀少,尤其是与指令和模板等内容的涵盖程度相比。

尽管如此,这比我发现的任何其他解决方案都容易 1000% 工作。

旁注:如果您在 angular.json 中而不是在 prod 配置下使用并ServiceWorkerModule.register('ngsw-worker.js', { enabled: true })移动到一般构建选项,则在调试时您不必再等待 5 分钟来进行 prod 构建。"serviceWorker": true,"ngswConfigPath": "ngsw-config.json"

PS 对OP 的侦查的道具使我的断点位于正确的位置。

于 2020-05-26T19:34:47.237 回答