带您一步一步开发一个PWA技术的web app离线应用
一、PWA是什么?
随着app的泛滥,技术人员在创求一种新的技术让app开发更快,更新更快,成本更低,他们看上了html5,但是html5在制作web app的过程中有以下问题:
如果解决以上问题,那么h5将是是远程app开发的一种颠覆,2017年谷歌退出了PWA技术。
PWA全称progressive web app,其核心主要有3块,Manifest、Service Workers和storage
Service Workers是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门。这个 API 之所以令人兴奋,是因为它可以支持离线体验,让开发者能够全面控制这一体验。
Service Workers要点:
它是一种 JavaScript 工作线程,无法直接访问 DOM。 服务工作线程通过响应 postMessage 接口发送的消息来与其控制的页面通信,页面可在必要时对 DOM 执行操作。
服务工作线程是一种可编程网络代理,让您能够控制页面所发送网络请求的处理方式,他可以拦截浏览器请求,将资源缓存在浏览器中,离线模式下任然可以访问资源,非常方便,看看下图
要安装服务工作线程,您需要通过在页面中对其进行注册来启动安装。 这将告诉浏览器服务工作线程 JavaScript 文件的位置。
二、bfwstudio中创建一个PWA应用
注意,pwa的应用必须在https或localhost本地下才能执行,本文使用在线webide开发工具bfwstudio,在线使用https进行开发
1、注册一个bfw的社区账号,http://www.bfw.wiki/
2、登录后打开bfwstudio for html,http://studio.bfw.wiki/Studio/Open/lang/html.html
3、新建一个空白项目,取名pwademo
4、首先在根目录下新建一个serviceworker.js,插入一下代码
const version = 'offline-cache-v2' // Serverice Worker 安装成功后触发该事件 self.addEventListener('install', function (event) { // sw.js 有更新,立即生效 event.waitUntil(self.skipWaiting()); }); // sw.js 有更新时触发该事件 self.addEventListener('activate', function (event) { event.waitUntil( Promise.all([ // 更新客户端 self.clients.claim(), // 删除旧版本的缓存对象 caches.keys().then(function (cacheList) { return Promise.all( cacheList.map(function (cacheName) { if (cacheName !== version) { return caches.delete(cacheName); } }) ); }) ]) ); }); // 网页发送请求触发该事件 self.addEventListener('fetch', function (event) { console.log('url is', event.request.url) event.respondWith( caches.match(event.request).then(function (response) { // 如果 Service Worker 有自己的返回,就直接返回,减少一次 http 请求 if (response) { return response; } // 如果 service worker 没有返回,那就得直接请求真实远程服务 var request = event.request.clone(); // 把原始请求拷过来 return fetch(request).then(function (httpRes) { // 请求失败了,直接返回失败的结果就好了。。 if (!httpRes || httpRes.status !== 200) { return httpRes; } // 请求成功的话,将请求缓存起来。 var responseClone = httpRes.clone(); caches.open(version).then(function (cache) { cache.put(event.request, responseClone); }); return httpRes; }); }) ); })
这个js文件负责监听 fetch 事件,拦截请求;对缓存做处理,请求再缓存中直接返回,不在缓存中则请求服务端,将响应的资源再缓存中备份一份。
5、在项目根目录下新建一个index.html文件,插入以下代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link href="css/index.css" rel="stylesheet"> </head> <body> <img src="images/banana.png" /> <script src="js/index.js"></script> <script> if ('serviceWorker' in navigator) { window.addEventListener('load', function() { navigator.serviceWorker.register('serviceworker.js').then(function(registration) { // Registration was successful console.log('ServiceWorker registration successful with scope: ', registration.scope); }, function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }); } </script> </body> </html>
'serviceWorker' in navigator 首先判断浏览器是否支持 Service Worker;
navigator.serviceWorker.register('serviceworker.js'') 这行代码即是注册 Service Worker,参数 serviceworker.js 是上面一步编写的js 文件,名字可以自定义,service worker 只要是拦截 http 请求,对资源进行缓存操作。
6、打开https预览按钮,在bfwstudio的预览->https菜单中
8、点击预览->新窗口预览,打开开发者工具,切换到application标签,我们看到我们的serviceworker启动成功了
我们看看clear strorage选项卡
切换到Cache选项卡
我们可以看到那些资源被缓存了
我们现在试试离线方式能不能打开网页,切换到service workers选项卡,勾线offline离线访问模式
然后你刷新一下刚才页面试试,是不是任然可以访问
打开网络network选项卡
可以看到离线模式下资源的请求访问都是通过serviceworker来缓存响应的,statuscode任然是200
那么如果我们不缓存所有的资源,有些资源我们不需要缓存,那么只要改下代码就好了
// 白名单 const whiteUrls = [ 'jquery.js', 'vue.js', ] self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request).then(function (cacheRes) { // ....... return fetch(request).then(function (httpRes) { if (!httpRes || httpRes.status !== 200) { return httpRes; } // 符合白名单的才放到缓存中,其它的正常请求 if (whiteUrls.findIndex(event.request.url) !== -1) { var responseClone = httpRes.clone(); caches.open('offline-cache-v1').then(function (cache) { cache.put(event.request, responseClone); }); } return httpRes; }); }) ); })
本项目所有的代码存在bfwstudio webide上,在线打开即可开发,地址http://studio.bfw.wiki/Studio/Open.html?projectid=15874608911762310073
网友评论0