【问题标题】:Angular7: Service worker does not function as expectedAngular7:服务工作者没有按预期运行
【发布时间】:2019-05-29 16:58:34
【问题描述】:

我有一个 Angular Service Worker,我缓存了声音(mp3 文件),以便可以离线播放。这里是ngsw-config-json

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js",
        "/*.svg",
        "/*.eot",
        "/*.woff",
        "/*.woff2",
        "/*.tff"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "prefetch",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/sounds/character1/**",
        "/assets/sounds/character2/**"
      ]
    }
  }]
}

在我的网络应用中,声音播放如下:

let audioLink = `/assets/sounds/${character}/${soundURL}`;
let player = new Audio(audioLink);
player.play()

网站离线工作。 HTML、CSS、JS、JSON 文件都被缓存了。但是声音不播放(当我尝试播放时,我在上面显示了一个错误)。

在 Chrome 开发者工具 > Application > Cache 中,我可以看到一些声音(路径),但不是全部。但是没有一个在离线工作。

有时会出现这些错误:

  • GET "path/to/file" net::ERR_ABORTED 504 (Gateway Timeout)
  • Uncaught (in promise) DOMException
  • Failed to load resource: net::ERR_INTERNET_DISCONNECTED

它有时也说manifest.json 有问题,但没有任何问题,因为它在在线时显示在开发人员工具的清单部分。

这个问题有什么解决办法吗?这不是 Chrome 错误,因为我在 Safari 和 Firefox 中也看到了相同的行为。我知道新的 chrome 版本有一个 bug,因为这个 bug,favicon.ico 没有离线显示

不确定这是否有帮助,但here 是托管 Web 应用程序的链接。如果您在 Chrome 开发者工具中看到网络标签,您可以看到 mp3 文件正在“下载”,但它们不能离线播放。

在生成生产网站 (ng build --prod --base-href="/") 后,我查看了 ngsw.json,这是我看到的(删除了一些行):

{
  "name": "assets",
  "installMode": "prefetch",
  "updateMode": "prefetch",
  "urls": [
    "/assets/sounds/character1/sound one.mp3",
    "/assets/sounds/character1/sound two.mp3",
    "/assets/sounds/character2/sound three.mp3"
    "/assets/sounds/character2/sound four.mp3"
  ],
  "patterns": []
}

Here 是完整生成的ngsw.json。一切都设置为预缓存而不是延迟缓存。

所有这些资产 URL 也在 "hashTable" 对象中。我还看到它们在 chrome 开发者工具(开发者工具 > 网络)中被下载,但我只在应用程序缓存部分看到其中一些(可能是总共 150 个中的前 20-30 个)。

我在这里做错了什么?这可能是 Angular 7 的错误吗?我已经看到关于类似问题的各种其他 StackOverflow 和 Reddit 问题。

我试过的东西正在改变

let audioLink = `/assets/sounds/${character}/${soundURL}`;

let audioLink = `assets/sounds/${character}/${soundURL}`;

(在开始时删除了斜线),但这并没有什么不同。

我完全确定所有声音文件路径都是正确的,因为网站在线运行时绝对没有错误。

除了上述之外,我尝试手动更改所有网址并在应该有空格的地方插入%20。例如,将"/assets/sounds/character1/sound one.mp3" 更改为"/assets/sounds/character1/sound%20one.mp3",但这也不起作用。

我注意到的一件事是,如果您第一次访问该网站,并等待所有声音下载,然后关闭您的互联网连接并试用该网站,所有声音都可以正常工作。但只有一段时间,通常大约 10-15 分钟,然后他们停止工作。我在 Chrome、Chrome Android、Firefox、Safari 和 IOS Safari 上进行了测试。

编辑:根据某人的建议,我尝试更改

{
  "name": "assets",
  "installMode": "prefetch",
  "updateMode": "prefetch",
  "urls": [
    "/assets/sounds/character1/sound one.mp3",
    "/assets/sounds/character1/sound two.mp3",
    "/assets/sounds/character2/sound three.mp3"
    "/assets/sounds/character2/sound four.mp3"
  ],
  "patterns": []
}

{
  "name": "assets",
  "installMode": "prefetch",
  "updateMode": "prefetch",
  "urls": [
    "/assets/sounds/**"
  ],
  "patterns": []
}

但同样的问题仍然存在:声音可能会离线缓存 10-15 分钟,之后就无法离线播放。我只能在 Chrome 和 Chrome Android 中对此进行测试。

【问题讨论】:

  • 是否可能占用了太多空间?看起来你的 fontawesome 图标也不起作用
  • @codeninja 谢谢你告诉我,我会调查的。我将尝试只保留 HTML、CSS 和 JS 文件以及 MP3 文件,看看它是否有效。
  • @codeninja 这似乎不是这里的问题。我从缓存中删除了所有字体,现在 chrome 说使用是 4.8/7701 mb。还有一件事,在我访问该网站后,声音可能会离线工作 10-15 分钟,但之后,它会抛出一个错误,提示找不到文件

标签: javascript angular service-worker angular7 angular-service-worker


【解决方案1】:

在@codeninja 的帮助下,我找到了问题的答案。

首先,audioLink 必须是声音的直接链接。我在 Github 上托管该网站,因此链接如下所示:

let url = `sounds/path_to_sound.mp3`
let audioLink = `https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/${url}`;

其次,我们不能只使用sound.play()Audio() 方法,我们必须使用HttpClient 检索音频。我不确定为什么,但 codeninja 建议 ngsw 缓存文件的方式与 Audio 类不兼容。我不确定这是否属实,但我发现离线时,我必须使用HttpClient 来检索音频 blob(如下所示)。如果没有,您会收到 response not Ok 错误。即使我给了直接链接https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/direct.mp3,它也会抛出同样的错误。

总而言之,代码如下:

首先有一个getSound()函数:

getSound(url) {
  return this.http.get(url, {responseType: 'blob'});
}

然后在另一个函数(playSound(url))中,我们有这个:

playSound(url) {
  let audioLink = `https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/${url}`;

  this.getSound(audioLink)
    .subscribe(data => {
      console.log(data);
      // data is an audio blob
      let url = URL.createObjectURL(data);

      let sound = document.createElement('audio');
      sound.src = url;
      sound.play();
    })
}

此外,我还必须更改我的ngsw-config.json。我只更改了“资产”部分,所以我将展示:

{
  "name": "assets",
  "installMode": "lazy",
  "updateMode": "prefetch",
  "resources": {
    "files": [
    ],
    "urls": [
       "https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/**"
    ]
  }
}

我也无法让它与“预取”一起使用。虽然缓存的声音现在离线播放,但它们只有在之前播放过时才会播放,因为它设置为“惰性”。

我在 Chrome、Chrome Android 和 Firefox 上测试了这个解决方案,它运行良好。

【讨论】:

  • 我真的很抱歉,但我不确定。我希望其他人能够向我解释。
【解决方案2】:

我已经尝试制作一个演示来隔离错误并且似乎可以正常工作。注意到应用缓存中有一些奇怪的 url:

不确定是否是导致问题的原因。您已经提到使设备离线后声音会起作用,我猜这是浏览器缓存而不是离线缓存。 当我尝试刷新页面时,声音永远不会起作用。我的猜测是 ngsw 的配置或 ngsw 缓存文件的方式与 Audio 类不兼容。

您可以通过首先使用 @angular/common/http 获取 blob 将 blob 传递到 Audio 来测试它是否有效。我认为这是因为音频文件似乎位于不同的缓存目录中(见截图)。由于某种原因,css/js 文件的存储方式似乎有所不同,并且音频文件只能通过 angular 访问(离线)。

因为评论太长,所以作为回复发布

【讨论】:

  • 我不确定是否是导致问题的音频类,我只是通过将播放音频的功能替换为let sound = document.createElement('audio'); sound.src = 'url'; sound.play(); 之类的东西来检查,我也有同样的问题问题
  • 我认为 Angular 没有正确缓存声音文件。源代码在哪里?
  • 这里是ngsw-config.json,这里是生成的ngsw.json。整个生成的网站是here。我尝试对ngsw-config.json 进行一些调整,但无济于事(例如将/assets/sounds/** 放在assetGroups 中,名称为app,但这不起作用;它导致了我在问题中描述的相同错误)。
猜你喜欢
  • 1970-01-01
  • 2010-10-08
  • 2017-12-05
  • 2019-06-14
  • 2019-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多