PWA初次体验

​ 前言:本示例不用安装任何东西

部分资源来自网络资源及PWA官网,不要把PWA想象的太复杂,跟着示例走一下,你行的。

PWA介绍

一个新的前端技术,PWA( 全称:Progressive Web App )也就是说这是个渐进式的网页应用程序。

官网:https://developers.google.com/web/progressive-web-apps/

是 Google 在 2015 年提出,2016年6月才推广的项目。是结合了一系列现代Web技术的组合,在网页应用中实现和原生应用相近的用户体验。

官网上给出 PWA 的宣传是 : Reliable ( 可靠的 )、Fast( 快速的 )、Engaging( 可参与的 )

Reliable :当用户从手机主屏幕启动时,不用考虑网络的状态是如何,都可以立刻加载出 PWA。

Fast:这一点应该都很熟悉了吧,站在用户的角度来考虑,如果一个网页加载速度有点长的话,那么我们会放弃浏览该网站,所以 PWA 在这一点上做的很好,他的加载速度是很快的。

Engaging : PWA 可以添加在用户的主屏幕上,不用从应用商店进行下载,他们通过网络应用程序 Manifest file 提供类似于 APP 的使用体验( 在 Android 上可以设置全屏显示哦,由于 Safari 支持度的问题,所以在 IOS 上并不可以 ),并且还能进行 ”推送通知” 。

PWA关键技术

  • Service Worker (可以理解为服务工厂)
  • Manifest (应用清单)
  • Push Notification(推送通知)

Service Worker

以下用SW来表示

SW 是什么呢?这个是离线缓存文件。我们 PWA 技术使用的就是它!SW 是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门,因为使用了它,才会有的那个 Reliable 特性吧,SW 作用于 浏览器于服务器之间,相当于一个代理服务器。

浏览器支持

顺便带一句:目前只能在 HTTPS 环境下才能使用SW,因为SW 的权利比较大,能够直接截取和返回用户的请求,所以要考虑一下安全性问题。

image

事件机制

image

功能(还是比较逆天的)

  • 后台数据的同步
  • 从其他域获取资源请求
  • 接受计算密集型数据的更新,多页面共享该数据
  • 客户端编译与依赖管理
  • 后端服务的hook机制
  • 根据URL模式,自定义模板
  • 性能优化
  • 消息推送
  • 定时默认更新
  • 地理围栏

生命周期

image

  • Parsed ( 解析成功 ): 首次注册 SW 时,浏览器解决脚本并获得入口点,如果解析成功,就可以访问到 SW 注册对象,在这一点中我们需要在 HTML 页面中添加一个判断,判断该浏览器是否支持 SW 。

  • Installing ( 正在安装 ):SW 脚本解析完成之后,浏览器会尝试进行安装,installing 中 install 事件被执行,如果其中有 event.waitUntil ( ) 方法,则 installing 事件会一直等到该方法中的 Promise 完成之后才会成功,如果 Promise 被拒绝,则安装失败,SW会进入 Redundant( 废弃 )状态。

  • Installed / Waiting (安装成功/等待中):如果安装成功,SW 将会进入这个状态。

  • Activating ( 正在激活 ):处于 waiting 状态的 SW 发生以下情况,将会进入 activating 状态中:

    当前已无激活状态的 worker 、 SW脚本中的 self.skipWaiting()方法被调用 ( ps: self 是 SW 中作用于全局的对象,这个方法根据英文翻译过来也能明白什么意思啦,跳过等待状态 )、用户已关闭 SW 作用域下的所有页面,从而释放了当前处于激活状态的 worker、超出指定时间,从而释放当前处于激活状态的 worker

  • Activated ( 激活成功 ):该状态,其成功接收了 document 全面控制的激活态 worker 。

  • Redundant ( 废弃 ):这个状态的出现时有原因的,如果 installing 事件失败或者 activating 事件失败或者新的 SW 替换其成为激活态 worker 。installing 事件失败和 activating 事件失败的信息我们可以在 Chrome 浏览器的 DevTools 中查看

一个很不错的全面介绍sw的教程:https://www.villainhr.com/page/2017/01/08/Service%20Worker%20%E5%85%A8%E9%9D%A2%E8%BF%9B%E9%98%B6

Manifest

Web App Manifest 是一个 W3C 规范,它定义了一个基于 JSON 的 List 。Manifest 在 PWA 中的作用有:

​ 能够将你浏览的网页添加到你的手机屏幕上

​ 在 Android 上能够全屏启动,不显示地址栏 ( 由于 Iphone 手机的浏览器是 Safari ,所以不支持哦)

​ 控制屏幕 横屏 / 竖屏 展示

​ 定义启动画面

​ 可以设置你的应用启动是从主屏幕启动还是从 URL 启动

​ 可以设置你添加屏幕上的应用程序图标、名字、图标大小

Push Notification

Push 和 Notification 是两个不同的功能,涉及到两个 API 。

​ Notification 是浏览器发出的通知消息。

​ Push 和 Notification 的关系,Push:服务器端将更新的信息传递给 SW ,Notification: SW 将更新的信息推送给用户。

PWA示例

准备

我们先创建一个关于 PWA 的项目文件夹,

进入文件夹下我们准备一张 120x120的图片一张,作为我们的应用程序图标。

创建一个 index.html 文件

创建一个 main.css 文件

创建一个 manifest.json 文件

创建一个 sw.js 文件

image

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Hello PWA</title><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><link rel="stylesheet" href="main.css"><link rel="manifest" href="manifest.json">
</head>
<body><h3>Hello PWA</h3>
</body>
<script>// 检测浏览器是否支持SWif(navigator.serviceWorker != null){navigator.serviceWorker.register('sw.js').then(function(registartion){console.log('支持sw:',registartion.scope)})}
</script>
</html>

main.css

h3{color: #f00;
}

manifest.json

short_name: “ " 用户主屏幕上的应用名字

display : “standalone" 设置启动样式,让您的网络应用隐藏浏览器的 URL 地址栏

start_url : “/“ 设置启动网址,如果不提供的话,默认是使用当前页面

theme_color : “ “ 用来告知浏览器用什么颜色来为地址栏等 UI 元素着色

background_color: “ ” 设置启动页面的背景颜色

icons:”” 就是添加到主屏幕之后的图标

{"name": "一个PWA示例","short_name": "PWA示例","start_url": "/index.html","display": "standalone","background_color": "#fff","theme_color": "#3eaf7c","icons": [{"src": "/youhun.jpg","sizes": "120x120","type": "image/png"}],
}

sw.js

看网上很多人都安装的hs和ngrok去调试,在这里为了照顾新手我是直接引用的sw

处理静态缓存,首先定义需要缓存的路径,以及需要缓存的静态文件的列表。

借助 SW 注册完成安装 SW 时,抓取资源写入缓存中。使用了一个方法那就是 self.skipWaiting( ) ,为了在页面更新的过程当中,新的 SW 脚本能够立刻激活和生效。

importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.1.0/workbox-sw.js");
var cacheStorageKey = 'minimal-pwa-1'
var cacheList=['/','index.html','main.css','youhun.jpg'
]
self.addEventListener('install',e =>{e.waitUntil(caches.open(cacheStorageKey).then(cache => cache.addAll(cacheList)).then(() => self.skipWaiting()))
})

处理动态缓存,我们监听 fetch 事件,在 caches 中去 match 事件的 request ,如果 response 不为空的话就返回 response ,最后返回 fetch 请求,在 fetch 事件中我们可以手动生成 response 返回给页面。

更新静态资源,缓存的资源会跟随着版本的更新会过期的,所以会根据缓存的字符串名称清除旧缓存。在新安装的 SW 中通过调用 self.clients.claim( ) 取得页面的控制权,这样之后打开页面都会使用版本更新的缓存。旧的 SW 脚本不在控制着页面之后会被停止,也就是会进入 Redundant 期。

self.addEventListener('fetch',function(e){e.respondWith(caches.match(e.request).then(function(response){if(response != null){return response}return fetch(e.request.url)}))
})
self.addEventListener('activate',function(e){e.waitUntil(//获取所有cache名称caches.keys().then(cacheNames => {return Promise.all(// 获取所有不同于当前版本名称cache下的内容cacheNames.filter(cacheNames => {return cacheNames !== cacheStorageKey}).map(cacheNames => {return caches.delete(cacheNames)}))}).then(() => {return self.clients.claim()}))
})

部署

我们可以把当前pwa目录的所有内容都扔进服务器中,或者coding Pages和gitHub Pages也是可以的,当然,记得开启https。在上变介绍过SW的权利比较大,为了安全性,我们使用https协议来访问。

试着访问一下,我们这里用的coding Pages并且绑定了自己的域名

打开 chrom 的调试工具,打开 application ,点击 service workers 之后我们会发现 sw.js 脚本已经存到了 SW 中 。

image

我们打开 Network 刷新页面一下,看看,我们的页面资源来自 SW 而不是其他的地方,在 Console 中也打印出了我们在 index.html 中判断的语句,浏览器支持就会打印出这一句话。

image

接下来我们断网操作,在 Application 中给 Offline 打上对勾就行啦。然后刷新页面,我们仍然能看到之前的页面,原因就是我们在上图看到,他的资源是从 SW 上获得到的。当我们第一次打开这个页面的时候,Resopnse 对象被存到了 Cache Storage ( 定义在 SW 规范中 ,相关资料请同学们自行查询啦 )中,我们看下图:

image

通过存放到 Cache Storage 中,我们下次访问的时候如果是弱网或者断网的情况下,就可以不走网络请求,而直接就能将本地缓存的内容展示给用户,优化用户的弱网及断网体验。

这个时候肯定会有同学在想,如果内容更新了,那么页面展示的内容是新内容呢还是旧内容呢?下面我们操作一下,打开 index.html 文件,我们在 body 中添加一个 p 标签 ,然后回到页面刷新。

image

image

我们看到,页面上的内容并没有显示出我刚刚添加的那个 p 标签。这说明了,我们拿到的数据还是从 Cache Storage 中获取到的,Cache Storage中的内容并没有更新,强制刷新也不行哦,那么我们怎么才能让我刚刚添加的那个 p 标签显示出来呢。

我们打开 sw.js 脚本文件,我们修改一下 cacheStorageKey。

image

修改后,我们再次打开该网址,强制刷新下或者关掉浏览器重新打开。

页面中出现了刚刚添加的P标签,我们再看一下 Cache Storage 中的缓存名字,已经被修改。

image

总结

如果是使用coding或者gitHub提供的pages服务,则需要注意最好绑定下独立域名。如果不绑定则注意下文件请求路径即可。

研究PWA门槛不低,部署的服务器要求HTTPS,ServiceWorker涉及API众多,需要单独学习,另外npm中也已经有这个包了https://www.npmjs.com/package/web-pwa ,玩玩可以,真正部署到项目生产环境可能坑很多,但有坑填坑,不折腾还叫前端么。

作者:小申同学
链接:https://www.jianshu.com/p/fad8aa9e277f
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

PWA介绍及快速上手搭建一个PWA应用相关推荐

  1. eclipse maven项目 class类部署不到tomcat下_Springboot介绍以及用Eclipse搭建一个简单的Springboot项目教程

    简述 本文主要介绍Springboot以及用Eclipse搭建一个简单的Springboot项目. Springboot简介 Springboot是由Pivotal团队提供的全新框架,其设计目的是用来 ...

  2. Android测试solo,SoloPi支付宝开源的 Android 专项测试工具的介绍与快速上手

    SoloPi支付宝开源的 Android 专项测试工具的介绍与快速上手 SoloPi:支付宝开源的 Android 专项测试工具的介绍与快速上手 MTSC2019大会上,Soloπ算是一次正式的在公众 ...

  3. 【Microsoft Azure 的1024种玩法】七十一.基于Azure Virtual Machines快速上手搭建Typecho博客系统

    [简介] Typecho 是基于 PHP5 构建的开源跨平台博客系统,Typecho开源跨平台博客系统相较于wordpress .hexo有一定的性能优势,是我们记录文章内容的最佳首选博客,那么本篇文 ...

  4. Echarts开源可视化库学习(一) 介绍与快速上手

    介绍 ECharts是一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safar ...

  5. phpstudy快速搭建网站_小白快速上手搭建属于自己的网站

    小白入门建站其实可以完全不需要代码方面的知识也可以建站. 想要在学习初期就拥有一个属于自己的网站,学习~装逼么? 步骤很简单: 一.域名选择:选购一个自己喜欢的域名,建议可以到阿里云或者腾讯云购买(域 ...

  6. less的基础用法介绍(快速上手 )

    目录 less介绍 如何使用? 使用less 嵌套写法 使用变量 混合 运算 转义 命名空间 映射 less中的注释 导入 less介绍 less本身是一门向后兼容的CSS扩展语言 相当于就是一种能够 ...

  7. RAID简单介绍和Linux如何搭建一个RAID

    RAID:Redundant Arrays of Inexpensive Disks,有"廉价磁盘构成的具有冗余能力的阵列"之意.简称磁盘阵列. 磁盘阵列是由很多价格较便宜的磁盘, ...

  8. LTspice快速上手--搭建简单RC电路

    1.安装并打开LTspice LTspice下载地址 打开LTspice: 2.搭建简单RC电路 2.1 新建原理图 单击File - New Schematic或者直接点击菜单栏中New Schem ...

  9. 如何快速的搭建一个个人博客网站

    经过我几天的沉浸式的研究,发现一款基于Node.js的静态博客程序,可以方便的生成静态网页托管在github和Heroku上. ​ 类似于jekyll.Octopress.WordPress,我们可以 ...

最新文章

  1. 【stanford C++】容器III——Vector类
  2. 大容量导入或导出的数据格式 -- Unicode字符格式
  3. JavaWeb——内置对象session与httpSession对象是同一个东西么?
  4. 最常用的6种原型文件格式对比
  5. Hibernate 持久化状态、HQL语句大全(转)
  6. 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛——E题 Seek the Joker II
  7. mysql根用户的密码是什么_Mysql忘记根用户密码 怎么办?
  8. window下从python开始安装科学计算环境
  9. 乌鲁木齐市建筑物矢量数据(Shp格式+带高度)
  10. 硕士学位论文(2022年) Latex模板 模板修改记录 总结
  11. html json编辑器,JSON.html HTML Editor
  12. 阿帕虎题库管理系统服务器,阿帕虎题库管理系统的教程
  13. 【计算机基础恶补】南桥北桥
  14. 希尔伯特曲线 java_希尔伯特曲线(示例代码)
  15. 嵌入式车牌识别与称重系统
  16. java查看jvm内存使用情况
  17. Oracle建表语句及日期处理(oracle)
  18. 详解CAN总线:CAN总线通信优先级机制
  19. 写了个自动批改小孩作业的代码
  20. illustrator插件-画板功能开发-插入页码-js脚本开发-ai插件

热门文章

  1. Hadoop ViewFs允许hdfs schema的重载
  2. 绩效管理流程是什么?
  3. Monaca Web IDE 初体验 —— 开发PhoneGap/Cordova应用程序,还用什么Eclipse/XCode!
  4. Realm 数据库的简单使用
  5. js获取html font size,JavaScript fontsize方法入门实例(按照指定的尺寸来显示字符串)...
  6. python使用matplotlib可视化、使用fontsize参数设置单个图像的字体的大小、使用rcParams.update参数全局设置字体的大小(font size)
  7. el-table点击禁用按钮,只禁用本行的编辑按钮,不影响其他行
  8. 软考:计算机技术与软件专业技术资格(水平)考试
  9. js 倒计时写法(三种:倒计时发送,倒计时时间,倒计时可用)
  10. 什么是端到端加密 (E2EE)?