最近接手维护一个海外Web,需要用到PWA技术,虽说这玩意面世得有七八年了,但一直不温不火,尤其国内几乎没啥浏览器支持,也鲜有人用。借机学了吧PWA,记录下。
目录
-
PWA是什么
-
有什么优势
-
制作一个PWA应用
manifest.json 配置文件
ServerWorker.js
-
自定义安装
-
局限性及现状
-
相关文档
PWA 是什么
PWA(Progressive Web Apps) 是Google发明的一项Web技术,简单来说,是对普通html5网站的以下几项增强,目的是让网站变的像App:
- 可在桌面安装同原生app一样的图标,使用该图标打开的网站无任何浏览器UI,看起来就是原生APP,并且支持沉浸式状态栏、支持桌面图标图片和名称自定义等,虽然实际上仍是使用浏览器打开的一个网站。
- 在一定程度上支持无网络离线使用:通过拦截网络请求设置和获取缓存实现。
- 支持消息推送通知等,就和app一样,而且支持桌面图标上显示消息badge。
- 支持后台进程,即便压根没有打开该网站,例如后台下载音视频、播放音乐等。
PWA 有什么优势
从上述描述也能看出,最大的优势就是像App,没有浏览器地址栏、没有浏览器工具栏,如果网页本身是模仿app界面,那么从桌面图标打开后,几乎和原app一毛一样,难以区分。对于轻型app,体验也接近。
无需上架app商店,无需庞大安装体积,还能完整保留Web的跨平台、即时更新。
手机端和PC端均支持,前提是使用支持PWA的浏览器.
怎样制作一个PWA应用
PWA本质上就是一个网站,制作方式和普通网站一样,html5+js+css,只不过需额外增加一个 json 配置文件,用于定义PWA应用的名称、图标、安装方式等元信息。
如果想实现自定义安装,就写一段安装代码,在支持PWA的浏览器上,默认已提供安装按钮。手机浏览器一般隐藏在菜单的“安装”中。pc浏览器一般显示在地址栏右侧。
同时再增加一个js文件实现Service worker,用于监听和拦截网络请求,完成缓存的设置、读取,实现离线支持。
如果有需要,还可以继续在该js中实现 消息推送、系统通知、后台任务。
- 创建 manifest.json 配置清单文件
清单文件中有非常多的属性可设置,最简单配置只需4个元素
{
"name": "我的第一个PWA",
"short_name":"我的PWA",
"icons": [
{
"src": "icons/512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url":".",
"display":"standalone"
}
name 代表安装后显示的图标名称
short_name 如果已填写了name的话,这项可以不设置
在清单中至少要提供
short_name和name中的一个。如果同时提供,系统会在用户安装应用时使用name,并在用户的主屏幕、启动器或空间有限的其他位置使用short_name。
icons 是要显示的图标的图片信息对象数组,至少要包含一个512尺寸的图片。src:相对于manifest文件的图片路径,type: 图片mime类型
start_url是启动页面url,一般为.或/
display 代表启动方式,一般填写 standalone即可,表示作为一个独立应用启动。
完整的清单可查看文档 developer.mozilla.org/zh-CN/docs/…
- 创建 Service worker
名字看起来似乎复杂,其实就是一个简单js文件,当然如果想实现完美的体验,例如后台通知、推送、同步等,那确实能搞得很复杂, 这里只演示一个最简单的PWA应用所需的js实现。
一个最简单的js文件,只需要监听fetch事件即可,即便监听后什么也不干。
// 监听install事件
self.addEventListener('install', function (e) {
console.log('Service Worker 状态: install');
});
// 监听activate事件
self.addEventListener('activate', function (e) {
console.log('Service Worker 状态: activate');
});
self.addEventListener('fetch', function (e) {
// 需要缓存的xhr请求
console.log("fetch 事件")
});
将以上代码保存为 sw.js
注意出于安全考虑, ServiceWorker 只允许在 https 网站上使用,所以也决定了PWA只支持https网站
- 在 网页的 head 区域引入 manifest.json和sw.js,一个最简单的PWA应用就算完成了
<link rel="manifest" href="/manifest.json">
<script src="/sw.js"></script>
在浏览器中(建议chrome或edge浏览器)打开该网站,没意外的情况下,地址栏右侧会看到安装图标,点击会弹出一个安装提醒
安装后,桌面会多出一个应用图标。手机端也一样
自定义安装代码
默认需要点击浏览器中提供的安装按钮,pc端比较明显,一般在地址栏右侧中显示,但手机端浏览器藏的比较深,需要从菜单中进入找“添加到手机”或“安装”。
有时想在页面中悬浮一个按钮,提示用户可以安装到桌面,此时可以在 beforeinstallprompt 事件中实现自定义提示。
假如首页是index.html, 先添加一个悬浮按钮
<button id="install" hidden style="position: fixed;
bottom: 67px;
left: 50%;
margin-left: -100px;
height: 35px;
width: 200px;
font-size: 16px;
text-align: center;
background: #03A9F4;
color: #fff;
border: 0;
line-height: 35px;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);">Install PWA</button>
然后监听 beforeinstallprompt事件
let installPrompt = null;
const installButton = document.querySelector("#install");
window.addEventListener("beforeinstallprompt", function(e) {
e.preventDefault();
installPrompt = e;
installButton.removeAttribute("hidden");
});
installButton.addEventListener("click", async () => {
if (!installPrompt) {
return;
}
installButton.setAttribute("hidden", "");
let result = await installPrompt.prompt();
console.log(`Install prompt was: ${result.outcome}`);
installPrompt = null;
});
点击就会弹出安装提示。
可能有jy要问,直接在
window.addEventListener("beforeinstallprompt中 调用e.prompt()不就可以了吗?然而这是不可以的,出于安全考虑,必须在用户的主动点击中才可触发该操作。
PWA的局限性
PWA相对于普通html5确实有一定优势,但作用又不是特别大,形同鸡肋,加之国内浏览器普遍不支持,用者更是寥寥。
相对来说,chrome、firefox、Safari对PWA的支持比较好,在国外有一定应用,尤其是Google Play 商店可上架PWA应用,对于在Google play上架App困难的,倒是可以考虑使用PWA替代。
浏览器支持:尽管主流浏览器如Chrome、Firefox和Safari支持PWA,但国内普遍不支持。
性能:在一些低端或老旧的移动设备上,PWA可能无法提供与高端设备相同的性能体验,毕竟本质还是Web。
集成度:无法完全利用移动设备的硬件特性。
用户习惯:用户可能更习惯于从应用商店下载应用,而不是通过Web访问PWA。
必须使用https:虽然目前https网站已不成问题,但多少也算是一个限制吧。
相关文档
MDN developer.mozilla.org/zh-CN/docs/…
Learn PWA web.dev/learn/pwa