看到PWA,似曾相识,但又感觉很模糊,于是乎,又重新翻阅文档,学习了一遍,顺便把相关知识学习了一下,比如service worker,workbox3。
PWA概念:全称:Progressive Web APP, 渐进式 Web 应用。
实际上是通过 Web 技术编写出的一个网页应用,加上App Manifest和Service Worker来实现PWA的安装和离线缓存等功能。
解决了哪些问题?
可以添加至主屏幕,点击主屏幕图标可以实现启动动画及隐藏地址栏
实现离线缓存功能
实现了消息推送
PWA的实现-Manifest 实现添加至主屏幕首先在index.html的head中引入manifest.json文件,尽可能早的引入
<head> ... <meta content="width=device-width, user-scalable=no" /> <link href="http://www.likecs.com/manifest.json"> <link type="text/css" href="http://www.likecs.com/main.css"> ... </head>然后编写manifest.json文件,参考文档:https://developer.mozilla.org/zh-CN/docs/Web/Manifest
{ "name": "Minimal PWA", // 必填 显示的插件名称 "short_name": "PWA Demo", // 可选 在APP launcher和新的tab页显示,如果没有设置,则使用name "description": "The app that helps you understand PWA", //用于描述应用 "display": "standalone", // 定义开发人员对Web应用程序的首选显示模式。standalone模式会有单独的 "start_url": "http://www.likecs.com/", // 应用启动时的url "theme_color": "#313131", // 桌面图标的背景色 "background_color": "#313131", // 为web应用程序预定义的背景颜色。在启动web应用程序和加载应用程序的内容之间创建了一个平滑的过渡。 "icons": [ // 桌面图标,是一个数组 { "src": "icon/lowres.webp", "sizes": "48x48", // 以空格分隔的图片尺寸 "type": "image/webp" // 帮助userAgent快速排除不支持的类型 }, { "src": "icon/lowres", "sizes": "48x48" }, { "src": "icon/hd_hi.ico", "sizes": "72x72 96x96 128x128 256x256" }, { "src": "icon/hd_hi.svg", "sizes": "72x72" } ] } PWA的实现-Service Worker 实现离线缓存Service worker,是 Chrome 团队提出和力推的一个 WEB API,就像介于服务器和网页之间的拦截器,能够拦截进出的http请求,从而完全控制你的网站。
最主要的特点:在页面中注册并安装成功后,运行于浏览器后台,不受页面刷新的影响,可以监听和拦截作用域范围内所有页面的 HTTP 请求。
网站必须使用 HTTPS,处于安全考虑,避免被攻击。除了使用贝蒂开发环境调试。
运行于浏览器后台,可以控制打开的作用域范围下所有的页面请求
单独的作用域范围,单独的运行环境和执行线程
不能操作页面 DOM ,但是可以通过事件机制来处理
事件驱动型服务线程
浏览器支持情况: 生命周期解析成功(parsed)、正在安装(installing)、安装整个(installed)、正在激活(activating)、激活成功(activated)、废弃(redundant)
若 installing 事件失败或 activeing 事件失败,service worker 都会被废弃。
实现离线缓存首先在index.html中注册sw.js
<script async src="http://www.likecs.com/js/script.js"></script> <script> // 注册 service worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js', {scope: 'http://www.likecs.com/'}).then(function (registration) { // 注册成功 console.log('ServiceWorker registration successful with scope: ', registration.scope); }).catch(function (err) { // 注册失败 :( console.log('ServiceWorker registration failed: ', err); }); } </script>编写sw.js
var cacheStorageKey = 'cachesName' var cacheList = [ // 注册成功后要立即缓存的资源列表 ] // 当浏览器解析完sw文件时触发install事件 self.addEventListener('install', function(e) { // install事件中一般会将cacheList中要换存的内容通过addAll方法,拉一遍放入caches中 e.waitUntil( caches.open(cacheStorageKey).then(function(cache) { return cache.addAll(cacheList) }) ) }) // 激活时触发activate事件 self.addEventListener('activate', function(e) { // active事件中通常做一些过期资源释放的工作,匹配到就从caches中删除 var cacheDeletePromises = caches.keys().then(cacheNames => { return Promise.all(cacheNames.map(name => { if (name !== cacheStorageKey) { return caches.delete(name); } else { return Promise.resolve(); } })); }); e.waitUntil( Promise.all([cacheDeletePromises]) ) }) self.addEventListener('fetch', function(e) { // 在此编写缓存策略, 需要根据不同文件的扩展名把不同的资源通过不同的策略缓存在caches中,各种css,js,html,图片,都需要单独搞一套缓存策略 e.respondWith( // 可以通过匹配缓存中的资源返回 caches.match(e.request) // 也可以从远端拉取 fetch(e.request.url) // 也可以自己造 new Response('自己造') // 也可以通过吧fetch拿到的响应通过caches.put方法放进chches ) }) workbox3