引言
Angular自带PWA NPM包可以供我们使用,减少了我们自己对service Worker的配置,但在应用中总会出现一些问题,这些问题可以通过虚拟路径ngsw/state来详细查看。
问题现象
前段时间在离线应用部署中发现,当我们的Deploy Url即项目名存在时,离线资源总是会请求网络资源,并且不会缓存到worker中,后来查看ngsw/state发现service worker处于降级运行状态。
细细查看代码发现,编译后的ngsw.json中的缓存资源路径是这样的
'''
"assetGroups": [
...
files: [
"/index.html": "hash1",
"/1.bundle.js": "hash2"
]
...
]
细心的人可能已经发现问题了,所有的资源的路径都是绝对路径,意思就是service worker中cache添加的都是绝对路径开头的资源名,而部署在App路径下的项目都会加上App的pathName,相对的资源路径实际上是host/pathname/${url}。
既然发现了问题,就很好解决了
解决办法
先看关于资源编译输出的相关代码
if (!options.watch && options.serviceWorker) {
for (const [locale, outputPath] of outputPaths.entries()) {
let localeBaseHref;
if (i18n.locales[locale] && i18n.locales[locale].baseHref !== '') {
localeBaseHref = path.posix.join(
options.baseHref || '',
i18n.locales[locale].baseHref === undefined
? `/${locale}/`
: i18n.locales[locale].baseHref,
);
}
try {
await augmentAppWithServiceWorker(
host,
root,
normalize(projectRoot),
normalize(outputPath),
localeBaseHref || options.baseHref || '/',// 聚焦这里
options.ngswConfigPath,
);
} catch (err) {
return { success: false, error: mapErrorToMessage(err) };
}
}
}
可以看到传递进serviceWorker的参数为options.baseHref||'/',那么问题也就可以解决了,首先配置文件里必须要有baseHref这个字段,其次,去掉ngsw-config.json中的绝对路径。
详细信息可以点击下面的连接查看
Anything else relevant?
The fix is easy: just remove the leading slash of all paths in ngsw-config.json template (including the index property).
这样就可以解决上述问题了。