写在前面
渐进式Web应用(PWA)是一种利用现代浏览器技术(如Service Workers和Web App Manifest)构建的Web应用,能提供类似原生APP的体验。
但是目前仅在Chrome系的浏览器上有较好的支持,Safari上的 文件-添加到程序坞 功能和PWA有很大的不同,Firefox直接不支持。
一、添加manifest.json文件
要想web应用支持安装到桌面,需要提供一个名为manifest.json的配置文件,通常放在public文件夹下,示例内容:
{
"short_name": "App short name",
"name": "App name",
"icons": [
{
"src": "/images/pwa/icon-192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/images/pwa/icon-512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"id": "your-app-id",
"start_url": "/",
"background_color": "#06605A",
"display": "standalone",
"scope": "/",
"theme_color": "#06605A",
"description": "Here is the description",
"screenshots": [
{
"src": "/images/pwa/screenshot-wide.png",
"sizes": "1280x720",
"type": "image/png",
"form_factor": "wide",
"label": "Desktop App"
},
{
"src": "/images/pwa/screenshot-narrow.png",
"sizes": "540x720",
"type": "image/png",
"form_factor": "narrow",
"label": "Mobile App"
}
]
}
然后记得在index.html中导入:
<link rel="manifest" href="/manifest.json" />
此时重启项目,你会看到一个安装按钮出现在导航栏右边:
点击安装即可将网页安装到桌面。
到此,一个最简单的PWA应用已经配置完成了,但是这个安装按钮很多人注意不到,通常我们需要在web里加一个引导Banner,点击后可以直接拉起安装弹窗,那么还需要以下配置~
二、注册一个Service worker
首先在public文件夹下创建一个sw.js文件,添加一行最小内容:
self.addEventListener('fetch', () => {});
然后在项目内任意地方写一个初始化函数,我通常会放到 src/pwa/index.ts 文件下,内容如下:
import store from '@/store';
const initPWA = () => {
// 注册一个空的service worker,否则无法手动触发pwa安装弹窗
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').catch(() => {
console.error('service worker registration failed');
});
}
// pwa安装提示事件监听
window.addEventListener('beforeinstallprompt', (e) => {
// 只有chrome内核浏览器才会触发这个事件
console.info('beforeinstallprompt event triggered');
// 在这里保存一下事件e,用于后面手动触发pwa安装弹窗
// 我这里用的全局状态管理工具是jotai,你也可以用别的,甚至挂载到window上也行
store.set(pwaInstallPromptAtom, e as BeforeInstallPromptEvent);
});
// pwa安装成功事件监听
window.addEventListener('appinstalled', () => {
// 只有chrome内核浏览器才会触发这个事件
console.info('appinstalled event triggered');
// 我目前没有发现哪个api能判断当前是否已经安装了pwa,所以就只能用localStorage自己存一下
localStorage.setItem('IS_PWA_INSTALLED', 'true');
});
};
export default initPWA;
然后记得在整个项目的入口文件调用一下initPWA函数,准备工作就做完了~
三、手动触发安装pwa弹窗
React代码如下:
import { useAtomValue } from 'jotai';
import { isSafari } from 'react-device-detect';
import { pwaInstallPromptAtom } from '../store';
const GuideToPwaBanner = () => {
// 拿到之前存的事件
const pwaInstallPrompt = useAtomValue(pwaInstallPromptAtom);
const handleInstall = async () => {
if (pwaInstallPrompt) {
// 拉起询问是否安装弹窗
await pwaInstallPrompt.prompt();
const { outcome } = await pwaInstallPrompt.userChoice;
if (outcome === 'accepted') {
// 走到这里就代表点了同意安装
}
} else if (isSafari) {
// 如果是safari浏览器,可以引导“添加到程序坞”
}
};
return <div onClick={handleInstall}>安装PWA</div>;
};
export default GuideToPwaBanner;
以上就是引导安装pwa的全部流程了~
写在末尾
1、配置了manifest.json,也没有出现安装按钮
在Devtools中可以检查是否成功加载了配置文件。
Service worker是否配置成功也可以在这个位置查看。
2、Safari的安装位置
这本质上是属于macos的能力,即使没有manifest.json也照样可以保存,但如果有manifest.json文件,那么添加到程序坞的应用程序也是可以读取到manifest的配置的。