当资源未缓存且离线时,Workbox 重定向客户端页面
Workbox redirect the clients page when resource is not cached and offline
通常每当我阅读有关 PWA 的博客 post 时,该教程似乎只是预缓存每个资产。但这似乎有点违背应用程序 shell 模式,据我了解,它是:缓存最基本的必需品(仅应用程序 shell),并在运行时缓存运行时。 (如果理解有误请指正)
假设我有这个单页应用程序,它是一个简单的 index.html,带有一个 Web 组件:<my-app>
。 <my-app>
组件设置了一些看起来有点像这样的路由,我正在使用 Vaadin 路由器和 Web 组件,但我想问题会与使用 React 和 React Router 或类似的东西一样。
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
}
]);
我的应用程序可能有很多路由,并且可能会变得非常大。我不想立即预缓存所有这些资源,而是只缓存我绝对需要的东西,所以在这种情况下:我的 index.html
、my-app.js
、app-main.js
和 app-offline.js
.我想在请求时在运行时缓存 app-posts.js
。
设置运行时缓存很简单,但是当我的用户访问尚未缓存的潜在许多路由之一时,我的问题就出现了(因为可能用户之前没有访问过该路由,所以 js
文件可能还没有 loaded/cached),并且用户没有互联网连接。
在那种情况下(当路由尚未缓存且没有网络时),我想要发生的是将用户重定向到 /offline
路由,该路由由我处理客户端路由器。我可以很容易地做类似的事情:import('./app-posts.js').catch(() => /* redirect user to /offline */)
,但我想知道是否有办法从工作箱本身实现这一点。
简而言之shell:
当 js
文件还没有被缓存,并且用户没有网络,因此文件请求失败:让 workbox 将页面重定向到 /offline
路由。
选项 1(并非总是有用):
据我所知,根据 ,您无法在服务工作者中打开新的 window 或更改浏览器的 URL。但是,如果 clients.openWindow()
函数 是从 和 notificationclick
中调用的,那么您只能打开一个新的 window 事件。
Option 2(最难):
您可以在 service worker 的 activate
事件中使用 WindowClient.navigate
方法,但是有点棘手,因为您仍然需要检查请求的文件是否存在于缓存中。
选项 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
.
通常每当我阅读有关 PWA 的博客 post 时,该教程似乎只是预缓存每个资产。但这似乎有点违背应用程序 shell 模式,据我了解,它是:缓存最基本的必需品(仅应用程序 shell),并在运行时缓存运行时。 (如果理解有误请指正)
假设我有这个单页应用程序,它是一个简单的 index.html,带有一个 Web 组件:<my-app>
。 <my-app>
组件设置了一些看起来有点像这样的路由,我正在使用 Vaadin 路由器和 Web 组件,但我想问题会与使用 React 和 React Router 或类似的东西一样。
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
}
]);
我的应用程序可能有很多路由,并且可能会变得非常大。我不想立即预缓存所有这些资源,而是只缓存我绝对需要的东西,所以在这种情况下:我的 index.html
、my-app.js
、app-main.js
和 app-offline.js
.我想在请求时在运行时缓存 app-posts.js
。
设置运行时缓存很简单,但是当我的用户访问尚未缓存的潜在许多路由之一时,我的问题就出现了(因为可能用户之前没有访问过该路由,所以 js
文件可能还没有 loaded/cached),并且用户没有互联网连接。
在那种情况下(当路由尚未缓存且没有网络时),我想要发生的是将用户重定向到 /offline
路由,该路由由我处理客户端路由器。我可以很容易地做类似的事情:import('./app-posts.js').catch(() => /* redirect user to /offline */)
,但我想知道是否有办法从工作箱本身实现这一点。
简而言之shell:
当 js
文件还没有被缓存,并且用户没有网络,因此文件请求失败:让 workbox 将页面重定向到 /offline
路由。
选项 1(并非总是有用):
据我所知,根据 clients.openWindow()
函数 是从 和 notificationclick
中调用的,那么您只能打开一个新的 window 事件。
Option 2(最难):
您可以在 service worker 的 activate
事件中使用 WindowClient.navigate
方法,但是有点棘手,因为您仍然需要检查请求的文件是否存在于缓存中。
选项 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
.