【发布时间】:2019-04-08 21:03:52
【问题描述】:
我正在构建 ReactJs PWA,但在 iOS 上检测更新时遇到问题。
在 Android 上一切正常,所以我想知道这一切是否与 iOS 对 PWA 的支持有关,或者我的 service worker 实现不好。
这是我到目前为止所做的:
构建过程和托管
我的应用是使用 webpack 构建并托管在 AWS 上的。大多数文件(js/css)都是在其名称中使用一些哈希构建的,由其内容生成。对于那些不是(应用程序清单、index.html、sw.js),我确保 AWS 为它们提供一些 Cache-Control 标头以防止任何缓存。一切都通过 https 提供。
服务工作者
我让这个尽可能简单:我没有为我的 app-shell 添加任何缓存规则,除了预缓存:
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
服务工作者注册
Service Worker 的注册发生在 ReactJs App 主组件中,在 componentDidMount() 生命周期钩子中:
componentDidMount() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then((reg) => {
reg.onupdatefound = () => {
this.newWorker = reg.installing;
this.newWorker.onstatechange = () => {
if (this.newWorker.state === 'installed') {
if (reg.active) {
// a version of the SW is already up and running
/*
code omitted: displays a snackbar to the user to manually trigger
activation of the new SW. This will be done by calling skipWaiting()
then reloading the page
*/
} else {
// first service worker registration, do nothing
}
}
};
};
});
}
}
Service Worker 生命周期管理
根据Google documentation about service workers,导航到范围内页面时应检测到新版本的服务工作者。但作为单页应用,一旦加载应用,就不会发生硬导航。
我找到的解决方法是连接到 react-router 并监听路由变化,然后手动要求注册的 service worker 进行自我更新:
const history = createBrowserHistory(); // from 'history' node package
history.listen(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.getRegistration()
.then((reg) => {
if (!reg) {
return null;
}
reg.update();
});
}
});
实际行为
在上面显示的代码中到处乱扔alert(),这是我观察到的:
- 将 pwa 添加到主屏幕后第一次打开时,Service Worker 已按预期注册,在 Android 和 iOS 上
- 在保持应用程序打开的同时,我在 AWS 上部署了一个新版本。由于我的历史监听器,在应用程序中导航会触发手动更新。找到新版本,后台安装。然后我的快餐栏就会显示出来,我可以触发切换到新的软件。
- 现在我关闭应用程序并在 AWS 上部署新版本。再次打开应用程序时:
- 在 Android 上,当 Android 重新加载页面时会立即找到更新
- iOS 没有,所以我需要在应用程序中导航,以便我的历史监听器触发更新搜索。这样做时,会发现更新
- 在这之后,对于两个操作系统,我的快餐栏都会显示,我可以触发切换到新的 SW
- 现在我关闭应用程序并关闭手机。部署新版本后,我再次启动它们并打开应用程序:
- 在 Android 上,就像以前一样,重新加载检测到更新的页面,然后显示小吃栏等。
- 在 iOS 上,我在应用程序中导航,我的侦听器触发搜索更新。 但这一次,新版本永远找不到,我的
onupdatefound事件处理程序也永远不会触发
阅读this post on Medium from Maximiliano Firtman,iOS 12.2 似乎为 PWA 带来了新的生命周期。据他介绍,当应用长时间处于空闲状态或设备重启期间,应用状态和页面都会被杀死。
我想知道这是否可能是我的问题的根本原因,但到目前为止我找不到遇到同样问题的人。
【问题讨论】:
-
What’s new on iOS 12.2 for Progressive Web Apps 也有更新。是的,到目前为止,iOS 上的 PWA 最糟糕的问题——如果不是最糟糕的——就是重新加载问题。我认为这是您问题的根本原因,因为 iOS 中新的 PWA 生命周期。
标签: ios reactjs progressive-web-apps