如何在Angular 5+服务工作者中处理路由?

时间:2018-02-01 14:54:21

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

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

使用Angular 5,ServiceWorkerModule已经很好地构建,现在可以使用ngsw-config.json文件处理大部分配置。但是,在I/O talkangular.io guide中的任何位置都不再提及如何处理路由的重定向。所以我最终遇到了以下问题:当我访问我的应用程序并离线时,我仍然可以直接访问该应用程序:documentation。但是,加载后,应用会重定向到search路由,大多数用户都会尝试从https://jackkoppa.github.io/cityaq-sw-issue这样的网址加载(为简单起见,我只是谈论Chrome桌面和移动设备) ,就目前而言,并在可能的情况下隐姓埋名。)

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

2 个答案:

答案 0 :(得分:8)

TL; DR:我发现至少有两个导致我案件破损的问题;您现在可以使用this build script来尝试我的修复,并看到该应用在线下工作here。进一步测试&需要拉动请求。

虽然我一直无法找到记录在案的答案,但这是我到目前为止能够找到的,通过ngsw-worker.js文件,以及阅读@angular/service-worker提交历史记录。

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

因此,导致我的网站在离线时失败的问题不能与路由直接相关,到目前为止我找到了2。通过解决方法纠正这些问题,使我的应用程序大部分按预期运行。通过原始问题中的重复步骤,cityaq现在正在运行,而我已在cityaq-sw-issue复制了原始的失败网站。

问题:

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

    • source
    • 我相当自信这个问题需要解决,而且我正在处理一个拉取请求来解决它。之所以会发生这种情况,是因为baseHref在生成ngsw.json时会被包含在资源网址中(source
  2. 在3个可用的"状态" ngsw-worker.js根据我的经验,EXISTING_CLIENTS_ONLY似乎打赌设置不正确。

    • source 1source 2
    • 我对这种变化缺乏信心,因为我无法一直看到 导致这种状态。但是,如果&当服务工作者进入此状态时,ngsw-worker.js将不再尝试检索缓存的资源(source),并且在我的测试中,似乎是"正确的"情况下,即使唯一的更改是删除互联网连接,应用仍会进入此状态
  3. 虽然我为问题#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
    4. "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. 本地运行
      2. npm run sw-build
        cd dist
        http-server -p 8080

        1. 在发送到服务器之前为您的实时网址准备一个版本(例如angular-cli-ghpages
        2. npm run sw-build-live

答案 1 :(得分:0)

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

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

使该死的事情变得如此困难的一件事是有多少种不同的方式指定路径和基础,并且其中一些非常适应,而另一些则非常严格。如果您的部署中断了,您实际上将无法使用内置调试,也无法像使用正常模块一样仅打开调试日志记录。这些文档非常稀疏,特别是与涵盖指令和模板之类的文档相比。

仍然,这比我发现的任何其他解决方案都容易上手1000%。

旁注::如果您使用ServiceWorkerModule.register('ngsw-worker.js', { enabled: true })并将"serviceWorker": true,"ngswConfigPath": "ngsw-config.json"移至angular.json中的常规构建选项,而不是在prod配置下,调试时无需等待5分钟即可生成产品。

P.S。支持OP's sleuthing的道具将我的断点放在正确的位置。