天人合一物我相融,站点升级渐进式Web应用PWA(Progressive Web Apps)实践
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_216
PWA(Progressive web apps,渐进式 Web 应用)使用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序,说白了,PWA可以让我们的站点以原生APP的形式运行,但相比于安装原生APP应用,访问PWA显然更加容易和迅速,还可以通过链接来分享PWA应用。
有许多知名的网络平台已经将 PWA 方案落地,比如Twitter。选择增强的网站体验而不是原生应用。事实上使用PWA也确实从中获得了显而易见的益处。https://www.pwastats.com 这个网站上分享了许多案例研究,PWA相比于传统应用有以下好处:
1、减少应用安装后的加载时间,通过 Service Workers 来进行缓存,以此来节省带宽和时间。
2、当应用有可用的更新时,可以只更新发生改变的那部分内容。相比之下,对于一个原生应用而言,即便是最微小的改动也需要强制用户去进行热更新或者再次下载整个应用。
3、外观和使用感受与原生平台更加融为一体——应用图标被放置在主屏幕上,应用可以全屏运行等。
凭借系统通知和推送消息与用户保持连接,对用户产生更多的吸引力,并且提高转换效率。
诚然,从零开始研发PWA应用会有一定的成本,但如果我们本身就拥有基于Web的站点,那么就可以通过增加对应的配置文件和服务进行升级操作,直接拥有PWA应用。
HTTPS服务
首先PWA要求站点的请求方式为HTTPS,如果是生产环境,可以通过为Nginx服务器配置SSL的方式进行适配,但是线下环境测试PWA时就有点费劲了,所以通过openssl工具为本地域名localhost做自签证书:
openssl req -x509 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-days 3650 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
产出:localhost.crt和localhost.key文件,key是私用密钥openssl格式,通常是rsa算法。csr是证书请求文件,用于申请证书,在制作csr文件的时,必须使用自己的私钥来签署申,还可以设定一个密钥。
将文件放到项目的根目录下,随后在构建项目服务的时候配置即可,以Tornado为例:
server = httpserver.HTTPServer(app,xheaders=True,ssl_options={
"certfile": "./localhost.crt",
"keyfile": "./localhost.key",
})
# 指定端口
server.listen(443)
这里通过设置ssl_options参数来导入私钥和证书,同时将端口改为HTTPS默认端口号443。如此,在本地也可以对PWA进行测试了,当然了,如果不需要本地操作,也可以跳过这步。
manifest.json配置文件
为了实现 PWA 应用添加至桌面的功能,除了要求站点支持 HTTPS 之外,还需要准备 manifest.json 文件去配置应用的图标、名称等信息。
以本站为例,在站点根目录创建manifest.json文件:
{
"name": "刘悦的技术博客",
"short_name": "刘悦的技术博客",
"description": "刘悦的技术博客",
"icons": [
{
"src": "https://v3u.cn/v3u/Public/images/pwa192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "https://v3u.cn/v3u/Public/images/pwa512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"background_color": "#FFF",
"theme_color": "#FFF",
"display": "standalone",
"orientation": "portrait",
"start_url": "/",
"scope": "/"
}
由上至下,依次是 PWA 应用的名称、描述、图标文件、banner颜色、显示方式、开始页面的链接和 PWA 的作用域。为此我们需要提供两张不同分辨率的站点图标文件:

ServiceWorker服务
Service Worker是一个注册在指定源和路径下的事件驱动型Web Worker。它充当了Web应用程序与浏览器之间的代理服务器,进行资源在文件级别下的缓存与操控,拦截页面请求,实现在不同的情况下对不同请求的响应策略。
Service Worker本质上就是一个Web Worker,因此它具有Web Worker的特点:无法操作DOM、脱离主线程、独立上下文。
Service Worker还具有这些特点:只能在Https下使用、运行在浏览器后台,不受页面刷新影响、更强大的离线缓存能力(使用Cache API)、请求拦截能力、完全异步,不能使用同步API、持续运行,第一次访问页面后,Service Worker就会安装激活并持续运行,直到手动销毁。
以本站为例,在站点根目录创建sw.js文件,注意Service Worker文件位置一定得在根目录,如果不在根目录也要通过重写或者url映射让其可以通过根目录路径进行访问,如:https://v3u.cn/sw.js,否则浏览器会检测不到Service Worker服务:
var CACHE_NAME = 'v3u-cache-v1';
var urlsToCache = [
'/',
'/v3u/Public/css/tidy_min.css'
];
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(CACHE_NAME).then(function (cache) {
console.log('Open cache');
return cache.addAll(urlsToCache);
}).then(function () {
self.skipWaiting();
})
);
});
当我们为页面注册Service Worker后,Service Worker开始进行安装,安装成功之后,会在worker中触发install事件;如果安装失败,则进入废弃状态。
如果Service Worker逻辑文件更新(相关资源文件变动或者内部逻辑更新等),Service Worker会重新安装,如果这个时候,页面依然存在激活状态下的worker(旧的Service Worker),那么新的worker会进入waiting状态进行等待,直到我们主动去操作worker强制其更新,或者等待用户关闭所有页面,这个时候新的worker才会进入到激活状态。
在install事件中,我们使用caches.open方法打开cache对象,并通过cache.addAll缓存所有我们列出的文件。如果Service Worker存在更新,我们使用skipWaiting跳过等待,直接强制新的worker进入激活状态。
随后,添加fetch事件:
self.addEventListener('fetch', function(event){
if(event.request.method !== 'GET') return;
event.respondWith(
caches.match(event.request).then(function(response){
if(response){
console.log('return caches');
return response;
}else{
return fetch(event.request).catch(function(){
if(/\.html$/.test(event.request.url))
return caches.match('/html/neterror.html');
});
}
})
)
});
这里只监听了全站的GET请求方式,即我们只希望控制资源请求。通过caches.match检查请求是否命中了缓存,如果命中,则直接返回缓存给用户,防止重复请求,节约资源。如果没有命中,则将使用fetch方法请求网络资源并返回给用户。当网络状态异常时(fetch().catch()),返回404页面的缓存给用户,告知用户当前处于无网络状态,不能访问相关页面。指定了一些页面和文件进行缓存,我们希望用户在无网络的情况下只能访问到我们指定缓存的页面。
当然,还有另外一种情况,我们指定了一些页面进行缓存(常用页面),当用户访问到一些不常用页面时,再对其进行缓存。这样,我们可以对资源配置进行优化,不过多的占用用户本地资源去缓存所有页面,因为PWA的缓冲本身是存储到客户端的,对于非所有用户的常用页面,按需缓存:
self.addEventListener('fetch', function(event){
if(event.request.method !== 'GET') return;
event.respondWith(
caches.match(event.request).then(function(response){
if(response){
console.log('return caches');
return response;
}else{
return fetch(event.request).then(function(res){
var responseToCache = res.clone();
caches.open(CACHE_NAME).then(function(cache){
catch.put(event.request, responseToCache);
})
return res;
});
}
})
)
});
至此,ServiceWorker服务文件就撰写完成了。
生产环境上线配置:
分别将manifest.json和sw.js文件分别上传到生产环境之后,在页面的head标签中进行声明:
<link rel="manifest" href="manifest.json">
声明后,注意访问一下是否正确返回:https://v3u.cn/manifest.json
随后在页面中注册Service Worker服务:
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () =>
navigator.serviceWorker.register("/sw.js?v0")
.catch(() => {}) // ignore
);
}
</script>
这里首先判断当前浏览器的navigator是否支持serviceWorker,随后使用navigator.serviceWorker.register函数来注册Service Worker。其中,参数为要执行的worker逻辑文件路径,注意这个路径是基于origin的,而非当前文件。
接着键入组合键,打开chrome浏览器的开发者工具:
Mac系统上的“⌥+⌘+I”
Win系统上的“F12+Ctrl+Shift+I”
在Chrome 的应用标签下进行检查,看应用清单有没有读出你的 PWA 应用信息配置文件:

随后在serviceWorker标签下检查serviceWorker是否正确运行:

接着访问站点,在地址栏即可添加PWA应用:

访问效果:

结语
渐进式增强和响应式设计已经可以让我们构建对移动端非常友好的站点,而PWA则又在我们的身后轻轻地推了一把,黄河之水源可滥觞,星星之火正在燎原,一年以内,我们都将感到PWA的灼人温度。
原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_216
天人合一物我相融,站点升级渐进式Web应用PWA(Progressive Web Apps)实践的更多相关文章
- PWA(Progressive Web App)入门系列:(一)PWA简单介绍
前言 PWA做为一门Google推出的WEB端的新技术,长处不言而喻.但眼下对于相关方面的知识不是非常丰富.这里我推出一下这方面的新手教程系列.提供PWA方面学习. 什么是PWA PWA全称Progr ...
- 关于PWA ( Progressive web apps )
渐进式Web应用程序使用现代Web API以及传统的渐进式增强策略来创建跨平台Web应用程序.这些应用程序无处不在,并提供多种功能,使其具有与本机应用程序相同的用户体验优势.这套文档告诉您需要了解的所 ...
- Progressive web app理念及发展前景
前一段时间微信推出微信小程序进行公测,着实火了一把,博得了大众的眼球,不明真相的吃瓜观众们纷纷围观,所谓的“微信小程序”,通俗的讲就是一种不需要下载安装即可使用的应用程序,脱离于app商店依托于浏览器 ...
- 试着给VuePress添加渐进式Web应用(PWA)支持,基于vuepress/plugin-pwa,点亮离线访问
背景 有时候,我们也希望VuePress构建的文档中心能支持离线访问,这时候我们需要给他添加渐进式Web应用(PWA,Progressive Web App)的支持,根据官方文档指引,我们可以借助插件 ...
- (转)PWA(Progressive Web App)渐进式Web应用程序
PWA 编辑 讨论 PWA(Progressive Web App)是一种理念,使用多种技术来增强web app的功能,可以让网站的体验变得更好,能够模拟一些原生功能,比如通知推送.在移动端利用标准化 ...
- PWA(Progressive web apps),渐进式 Web 应用
学习博客:https://www.jianshu.com/p/098af61bbe04 学习博客:https://www.zhihu.com/question/59108831 官方文档:https: ...
- Web应用托管服务(Web+)隐藏的十个上云最佳姿势
随着云计算浪潮的推进,技术架构云化已经成为大势所趋.特别是最近由CNCF推动的云原生概念,将符合云原生标准的各种开源技术方案推向了前所未有的高度.在这一波浪潮的推动下,越来越多的企业开始了自身的数字化 ...
- Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问
本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这 ...
- 转 web项目中的web.xml元素解析
转 web项目中的web.xml元素解析 发表于1年前(2014-11-26 15:45) 阅读(497) | 评论(0) 16人收藏此文章, 我要收藏 赞0 上海源创会5月15日与你相约[玫瑰里 ...
随机推荐
- SQL连接查询优化[姊妹篇.第五弹]
上篇的sql优化篇章,更多偏向于优化的思想概念,先前抛出的4个优化问题中,篇幅过长,只对前两个问题进行了解析. 接下来我们一起来谈谈sql的连接查询优化,更偏向于实际运用,并对如下两个问题进行探讨.篇 ...
- 使用 VS Code + Markdown 编写 PDF 文档
背景介绍 作为一个技术人员,基本都需要编写技术相关文档,而且大部分技术人员都应该掌握 markdown 这个技能,使用 markdown 来编写并生成 PDF 文档将会是一个不错的体验,以下就介绍下如 ...
- L2M-GAN: Learning to Manipulate Latent Space Semantics for Facial Attribute Editing阅读笔记
L2M-GAN: Learning to Manipulate Latent Space Semantics for Facial Attribute Editing 2021 CVPR L2M-GA ...
- 20 HTTP 长连接与短连接
20 HTTP 长连接与短连接 每日一句 纸上得来终觉浅,绝知此事要躬行. 每日一句 Never give up until the fight is over. 永远不要放弃,要一直战斗到最后一秒. ...
- JavaSE_多线程入门 线程安全 死锁 状态 通讯 线程池
1 多线程入门 1.1 多线程相关的概念 并发与并行 并行:在同一时刻,有多个任务在多个CPU上同时执行. 并发:在同一时刻,有多个任务在单个CPU上交替执行. 进程与线程 进程:就是操作系统中正在运 ...
- pandas:多层索引
多层索引是指在行或者列轴上有两个及以上级别的索引,一般表示一个数据的几个分项. 1.创建多层索引 1.1通过分组产生多层索引 1.2由序列创建 1.3由元组创建 1.4可迭代对象的笛卡尔积 1.5将D ...
- 2021蓝桥杯省赛C++A组试题E 回路计数 状态压缩DP详细版
2021蓝桥杯省赛C++A组试题E 回路计数 状态压缩DP 题目描述 蓝桥学院由21栋教学楼组成,教学楼编号1到21.对于两栋教学楼a和b,当a和b互质时,a和b之间有一条走廊直接相连,两个方向皆可通 ...
- while循环、do..while循环
While循环 While循环呢它是更具条件来判断是否执行大括号里的内容 ,只要条件成立就会一值执行直到不满足条件它的语法格式: while(循环条件){ 执行语句 }那么我们来做一个小测试看看: p ...
- JS:自增和自减
自增自减是一元操作符运算 1.++: 前置++:先把取值,再把变量的值加1 后置++:先把变量的值加1,再取值 2.--: 前置--:先把取值,再把变量的值加1 后置--:先把变量的值加1,再取值 v ...
- 你要的几个JS实用工具函数(持续更新)
今天,我们来总结下我们平常使用的工具函数,希望对大家有用.1.封装fetch 源码: /** * 封装fetch函数,用Promise做回调 * @type {{get: (function(*=)) ...