【问题标题】:How to handle routing in Angular 5+ Service Workers?如何在 Angular 5+ Service Worker 中处理路由?
【发布时间】:2018-07-11 22:45:16
【问题描述】:

在以前版本的 Angular 服务工作者实现中,配置选项之一是 "routing"。这可以在这个unanswered SO question 中看到,在这个Angular CLI issue 中被引用,剩下的最好的文档似乎是blog post by Stephen Fluin(在Angular 团队中),以及来自Alex Rickabaugh 的I/O talk(来自Google )。

使用 Angular 5,ServiceWorkerModule 已经很好地构建了,现在可以使用ngsw-config.json 文件处理大部分配置。但是,在angular.io guidedocumentation 中的任何位置都不再提及如何处理路由重定向。所以我最终遇到了以下问题:当我访问我的应用程序并离线时,我直接访问它时仍然可以访问应用程序: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 文件中处理解决方法?

【问题讨论】:

  • 我真的很想知道这个问题的答案
  • @stephenagwu 同意了。我无法在任何地方找到文档,这让我觉得我可能会在 Angular repo 上将其写成一个问题。不过,希望在这之前有人对服务人员有更好的了解,尽管
  • 当我第一次注意到这种行为时,我打开了一个问题。就像你说的,它在 v5 之前运行良好。但是,对于 SW,我不确定问题出在 Angular 还是 CLI(构建 ngsw-worker.js)上。我已经在 Angular repo github.com/angular/angular/issues/21636 上打开了它
  • 我创建了a repo,它与@MrCroft 在上面链接的问题中找到的最小复制步骤相匹配。仍在尝试深入了解ngsw-worker.js 在获取过程中失败的位置。
  • 将让赏金到期,因为感觉我们对 Angular 团队的期望没有任何完整的答案。希望我可以继续处理我的回答中描述的拉取请求,或者有更多知识的人偶然发现这个

标签: angular angular-cli angular-routing service-worker angular-service-worker


【解决方案1】:

我只是不得不处理这个几天,虽然我没有使用路由,只是一个非根基础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. 您的应用将发出 "/route/index.html""/route/main.js" 之类的请求,因为 baseHref 与在其下进行哈希处理并实际缓存的键相匹配。
  7. Service Worker 已在 /route/ 下正确注册,因此它将 a.) 尝试处理请求并 b.) 在您离线时在其缓存中找到它们。

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

不过,这比我找到的任何其他解决方案都容易 1000%。

旁注:如果您使用 ServiceWorkerModule.register('ngsw-worker.js', { enabled: true }) 并将 "serviceWorker": true,"ngswConfigPath": "ngsw-config.json" 移动到 angular.json 中的常规构建选项而不是 prod 配置下,则您没有调试时要额外等待 5 分钟以进行产品构建。

附:对 OP's sleuthing 的道具,它使我的断点位于正确的位置。

【讨论】:

    【解决方案2】:

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


    虽然我无法找到记录在案的答案,但这是我迄今为止在逐步浏览ngsw-worker.js 文件以及阅读@angular/service-worker 提交历史时能够找到的内容。

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

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

    问题:

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

      • source
      • 我相当有信心这个问题需要解决,我将处理一个拉取请求来解决它。这是因为baseHref 在生成ngsw.json 时包含在资源URL 中(source
    2. ngsw-worker.js 可以处于的3 个可用“状态”中,根据我的经验,EXISTING_CLIENTS_ONLY 似乎下注设置不正确。

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

    虽然我为问题 #1 整理了一个 PR,并等待一些帮助理解问题 #2,但我正在使用解决方法构建脚本在生成 ngsw-worker.js 后对其进行修改。警告:这很丑陋,并且肯定会修改设置EXISTING_CLIENTS_ONLY 的预期“安全”行为。但是,对于我的应用程序,它在本地运行 (http-server) 和部署到实时 URL(在我的情况下为 GitHub 页面)时确实允许正确的离线性能。

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

    1. npm install replace-in-file --save-dev
    2. 在您的应用中包含 this script,例如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-server -p 8080
    1. 并在发送到服务器之前为您的实时 URL 准备构建(例如使用 angular-cli-ghpages

    npm 运行 sw-build-live

    【讨论】:

    • 您的解决方案运行良好。谢谢 !但是控制台中仍然存在 504 错误。你知道如何处理吗?或者我应该等待这个修复 github.com/angular/angular/pull/22883 在下一个 Angular 版本中合并?
    • 是的,在我们看到 PR 如何影响问题之前,我不会花费太多精力来使用构建脚本解决 504。 github.com/angular/angular/issues/21636 也很适合观看任何其他更新
    • Angular 6 中是否仍需要此修复程序?我有 Angular 6.0.8 并且在离线模式下遇到 504 错误。
    • @JoshJobin - 这是一个很好的问题,我希望它不是必需的。或者至少,如果仍然存在 Service Worker 问题,它们不再是这 2 个。我已经几个月没有回到我的 cityAQ 项目了,但是我创建了an issue to upgrade to Angular 6,这样我就可以测试没有什么可以工作构建脚本。希望在八月之前有更新,那时我有更多的时间来做这个项目。同时,希望其他人能得到比我更近的答案?
    • @JackKoppa 我看到的证据表明 Angular 6 没有解决这个问题。
    猜你喜欢
    • 2018-07-21
    • 1970-01-01
    • 2018-05-21
    • 2018-10-06
    • 2017-12-24
    • 2020-02-01
    • 2018-06-04
    • 2018-12-02
    • 2016-10-10
    相关资源
    最近更新 更多