Angular7:服务工作者未按预期运行
Angular7: Service worker does not function as expected
我有一个 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 中,我可以看到有一些声音(路径),但不是全部。但是 none 正在离线工作。
有时会出现这些错误:
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 版本中有一个错误,由于这个错误,favicon.ico
没有显示为离线
不确定这是否有帮助,但 here 是托管 Web 应用程序的 link。如果您在 Chrome 开发人员工具中看到网络选项卡,您可以看到 mp3 文件是 'downloading',但它们不能离线播放。
生成用于生产的网站 (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 错误吗?我已经看到关于类似问题的各种其他 Whosebug 和 Reddit 问题。
我试过的东西正在改变
let audioLink = `/assets/sounds/${character}/${soundURL}`;
到
let audioLink = `assets/sounds/${character}/${soundURL}`;
(删除了开头的斜杠),但这并没有什么不同。
我完全确定所有声音文件路径都是正确的,因为当网站 运行 在线时绝对没有错误。
除上述之外,我尝试手动更改所有网址并在应该是 space 的地方插入 %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.
中进行测试
我已经尝试制作一个演示来隔离错误并且似乎有效。在应用程序缓存中注意到一些奇怪的 url:
不确定这是导致问题的原因。您已经提到在您使设备离线后声音有效,我猜这是浏览器缓存而不是离线缓存。
当我尝试刷新页面时,声音根本不起作用。我的猜测是 ngsw 的配置或 ngsw 缓存文件的方式与音频不兼容 class.
您可以通过先使用 @angular/common/http
获取 blob 将其传递到 Audio 来测试它是否有效。我认为这是因为音频文件似乎位于不同的缓存目录中(请参见屏幕截图)。由于某种原因,css/js 文件的存储方式似乎有所不同,音频文件只能由 angular.
访问(离线)
作为回复发布,因为评论太长了
我在@codeninja 的帮助下找到了问题的答案。
首先,audioLink
必须直接 link 声音。我在 Github 上托管网站,所以 link 看起来像这样:
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
class 不兼容。我不确定这是否属实,但我发现在离线时,我不得不使用 HttpClient
来检索音频 blob(如下所示)。否则,您会收到 response not Ok
错误。即使我直接给出 link 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
。我只更改了 "assets" 部分,所以我将展示:
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
],
"urls": [
"https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/**"
]
}
}
我也无法让它与 "prefetch" 一起工作。虽然缓存的声音现在可以离线播放,但它们只会在之前播放过的情况下播放,因为它被设置为 "lazy".
我在 Chrome、Chrome Android 和 Firefox 上测试了这个解决方案,它工作正常。
我有一个 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 中,我可以看到有一些声音(路径),但不是全部。但是 none 正在离线工作。
有时会出现这些错误:
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 版本中有一个错误,由于这个错误,favicon.ico
没有显示为离线
不确定这是否有帮助,但 here 是托管 Web 应用程序的 link。如果您在 Chrome 开发人员工具中看到网络选项卡,您可以看到 mp3 文件是 'downloading',但它们不能离线播放。
生成用于生产的网站 (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 错误吗?我已经看到关于类似问题的各种其他 Whosebug 和 Reddit 问题。
我试过的东西正在改变
let audioLink = `/assets/sounds/${character}/${soundURL}`;
到
let audioLink = `assets/sounds/${character}/${soundURL}`;
(删除了开头的斜杠),但这并没有什么不同。
我完全确定所有声音文件路径都是正确的,因为当网站 运行 在线时绝对没有错误。
除上述之外,我尝试手动更改所有网址并在应该是 space 的地方插入 %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.
中进行测试我已经尝试制作一个演示来隔离错误并且似乎有效。在应用程序缓存中注意到一些奇怪的 url:
不确定这是导致问题的原因。您已经提到在您使设备离线后声音有效,我猜这是浏览器缓存而不是离线缓存。 当我尝试刷新页面时,声音根本不起作用。我的猜测是 ngsw 的配置或 ngsw 缓存文件的方式与音频不兼容 class.
您可以通过先使用 @angular/common/http
获取 blob 将其传递到 Audio 来测试它是否有效。我认为这是因为音频文件似乎位于不同的缓存目录中(请参见屏幕截图)。由于某种原因,css/js 文件的存储方式似乎有所不同,音频文件只能由 angular.
作为回复发布,因为评论太长了
我在@codeninja 的帮助下找到了问题的答案。
首先,audioLink
必须直接 link 声音。我在 Github 上托管网站,所以 link 看起来像这样:
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
class 不兼容。我不确定这是否属实,但我发现在离线时,我不得不使用 HttpClient
来检索音频 blob(如下所示)。否则,您会收到 response not Ok
错误。即使我直接给出 link 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
。我只更改了 "assets" 部分,所以我将展示:
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
],
"urls": [
"https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/**"
]
}
}
我也无法让它与 "prefetch" 一起工作。虽然缓存的声音现在可以离线播放,但它们只会在之前播放过的情况下播放,因为它被设置为 "lazy".
我在 Chrome、Chrome Android 和 Firefox 上测试了这个解决方案,它工作正常。