service-worker - 当资源未缓存且脱机时,Workbox 重定向客户端页面
问题描述
通常,每当我阅读有关 PWA 的博客文章时,该教程似乎只是预先缓存了每一个资产。但这似乎有点违背应用程序外壳模式,据我了解,这是:缓存基本必需品(仅应用程序外壳),并在运行时缓存。(如果我理解不正确,请纠正我)
想象一下,我有这个单页应用程序,它是一个带有 web 组件的简单 index.html <my-app>
:. 该<my-app>
组件设置了一些看起来有点像这样的路由,我正在使用 Vaadin 路由器和 Web 组件,但我想使用 React 和 React 路由器或类似的东西会出现相同的问题。
router.setRoutes([
{
path: '/',
component: 'app-main', // statically loaded
},
{
path: '/posts',
component: 'app-posts',
action: () => { import('./app-posts.js');} // dynamically loaded
},
/* many, many, many more routes */
{
path: '/offline', // redirect here when a resource is not cached and failed to get from network
component: 'app-offline', // also statically loaded
}
]);
我的应用程序可能有很多很多路线,并且可能会变得非常大。我不想立即预缓存所有这些资源,而只缓存我绝对需要的东西,所以在这种情况下: my index.html
, my-app.js
,app-main.js
和app-offline.js
. 我想app-posts.js
在运行时缓存,当它被请求时。
设置运行时缓存很简单,但是当我的用户访问可能尚未缓存的许多路由之一时,我的问题就出现了(因为用户之前可能没有访问过该路由,所以js
文件可能没有加载/缓存然而),并且用户没有互联网连接。
在这种情况下(当路由尚未缓存且没有网络时)我想要发生的事情是将用户重定向到/offline
由我的客户端路由器处理的路由。我可以轻松地做类似的事情:import('./app-posts.js').catch(() => /* redirect user to /offline */)
,但我想知道是否有办法从工作箱本身实现这一点。
所以简而言之:当一个js
文件还没有被缓存,并且用户没有网络,所以对文件的请求失败:让工作箱将页面重定向到/offline
路由。
解决方案
选项 1(并不总是有用):
据我所知,根据这个答案,您无法从服务人员中打开新窗口或更改浏览器的 URL。但是,只有在事件中调用该clients.openWindow()
函数时,您才能打开一个新窗口。notificationclick
选项 2(最难):
您可以在 service worker 事件中使用该WindowClient.navigate
方法,activate
但是有点棘手,因为您仍然需要检查请求的文件是否存在于缓存中。
选项 3(最简单和最黑客):
否则,您可以使用新Request
对象响应离线页面:
const cacheOnly = new workbox.strategies.CacheOnly();
const networkFirst = new workbox.strategies.NetworkFirst();
workbox.routing.registerRoute(
/\/posts.|\/articles/,
async args => {
const offlineRequest = new Request('/offline.html');
try {
const response = await networkFirst.handle(args);
return response || await cacheOnly.handle({request: offlineRequest});
} catch (error) {
return await cacheOnly.handle({request: offlineRequest})
}
}
);
然后在你的offline.html
文件中重写浏览器的 URL:
<head>
<script>
window.history.replaceState({}, 'You are offline', '/offline');
</script>
</head>
上述选项 3中的逻辑将首先使用网络响应请求的 URL。如果网络不可用,将回退到缓存,即使在缓存中找不到请求,也会offline.html
取而代之获取文件。解析offline.html
文件后,浏览器 URL 将替换为/offline
.
推荐阅读
- r - 用两个data.table制作一个data.table,名称为column[2],不同
- python - 在python中层次聚类的每一步打印所有聚类和样本
- linux - 将函数调用输出记录到 GDB 中的文件
- java - android - 将 int array [] 转换为设置文本
- java - Spring Boot 调度程序服务的负载均衡
- reactjs - 带有 nextjs 的 G2Plot。堆积图不起作用
- python - Fitler DateTimeField 与 django-filter 中的 DateFilter
- apache-spark - PySpark:仅针对某些字段读取具有已定义固定类型的 JSON 文件
- javascript - google drive api TypeError:无法读取未定义的属性“驱动器”或类型错误:无法读取未定义的属性“文件”
- keras - Keras 教程 - 获取规范化层时出错