网站PWA升级
前面的话
渐进式网络应用 ( Progressive Web Apps ),即我们所熟知的 PWA,是 Google 提出的用前沿的 Web 技术为网页提供 App 般使用体验的一系列方案。PWA 本质上是 Web App,借助一些新技术也具备了 Native App 的一些特性。本文将详细介绍针对现有网站的PWA升级
效果演示
以前端小站xiaohuochai.cc的PWA效果做演示,github移步至此
【添加到桌面】

【离线缓存】
由于手机录屏选择无法进行离线录制,改由模拟器模拟离线效果

概述
PWA 的主要特点包括下面三点:
1、可靠 - 即使在不稳定的网络环境下,也能瞬间加载并展现
2、体验 - 快速响应,并且有平滑的动画响应用户的操作
3、粘性 - 像设备上的原生应用,具有沉浸式的用户体验,用户可以添加到桌面
主要功能包括站点可添加至主屏幕、全屏方式运行、支持离线缓存、消息推送等
【PRPL模式】
“PRPL”(读作 “purple”)是 Google 的工程师提出的一种 web 应用架构模式,它旨在利用现代 web 平台的新技术以大幅优化移动 web 的性能与体验,对如何组织与设计高性能的 PWA 系统提供了一种高层次的抽象
“PRPL”实际上是 Push/Preload、Render、Precache、Lazy-Load 的缩写
1、PUSH/PRELOAD,推送/预加载初始 URL 路由所需的关键资源
2、RENDER,渲染初始路由,尽快让应用可被交互
3、PRE-CACHE,用 Service Worker 预缓存剩下的路由
4、LAZY-LOAD 按需懒加载、懒实例化剩下的路由
【Service workers】
Service Workers 是谷歌 chrome 团队提出并大力推广的一项 web 技术。在 2015 年,它加入到 W3C 标准,进入草案阶段
PWA 的关键在于 Service Workers 。就其核心来说,Service Workers 只是后台运行的 worker 脚本。它们是用 JavaScript 编写的,只需短短几行代码,它们便可使开发者能够拦截网络请求,处理推送消息并执行许多其他任务
Service Worker 中用到的一些全局变量:
self: 表示 Service Worker 作用域, 也是全局变量
caches: 表示缓存
skipWaiting: 表示强制当前处在 waiting 状态的脚本进入 activate 状态
clients: 表示 Service Worker 接管的页面
Service Worker 的工作机制大致如下:用户访问一个具有 Service Worker 的页面,浏览器就会下载这个 Service Worker 并尝试安装、激活。一旦激活,Service Worker 就到后台开始工作。接下来用户访问这个页面或者每隔一个时段浏览器都会下载这个 Service Worker,如果监测到 Service Worker 有更新,就会重新安装并激活新的 Service Worker,同时 revoke 掉旧的 Service Worker,这就是 SW 的生命周期
因为 Service Worker 有着最近的权限接触数据,因此 Service Worker 只能被安装在 HTTPS 加密的页面中,虽然无形当中提高了 PWA 的门槛,不过也是为了安全做考虑
离线缓存
下面来通过service worker实现离线缓存
一般地,通过sw-precache-webpack-plugin插件来实现动态生成service worker文件的效果
不过,首先要在index.html中引用service worker
<script>
(function() {
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
})()
</script>
【SPA】
通过create-react-app生成的react SPA应用默认就进行了sw-precache-webpack-plugin的设置。但是,其只对静态资源进行了设置
如果是接口资源,则一般的处理是优先通过网络访问,如果网络不通,再通过service worker的缓存进行访问
webpack.config.prod.js文件的配置如下
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
new SWPrecacheWebpackPlugin({
// By default, a cache-busting query parameter is appended to requests
// used to populate the caches, to ensure the responses are fresh.
// If a URL is already hashed by Webpack, then there is no concern
// about it being stale, and the cache-busting can be skipped.
dontCacheBustUrlsMatching: /\.\w{}\./,
filename: 'service-worker.js',
logger(message) {
if (message.indexOf('Total precache size is') === ) {
// This message occurs for every build and is a bit too noisy.
return;
}
if (message.indexOf('Skipping static resource') === ) {
// This message obscures real errors so we ignore it.
// https://github.com/facebookincubator/create-react-app/issues/2612
return;
}
console.log(message);
},
minify: true,
// For unknown URLs, fallback to the index page
navigateFallback: publicUrl + '/index.html',
// Ignores URLs starting from /__ (useful for Firebase):
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
navigateFallbackWhitelist: [/^(?!\/__).*/],
// Don't precache sourcemaps (they're large) and build asset manifest:
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
runtimeCaching: [{
urlPattern: '/',
handler: 'networkFirst'
},
{
urlPattern: /\/api/,
handler: 'networkFirst'
}
]
})
【SSR】
如果是服务器端渲染的应用,则配置基本类似。但由于无法使用代理,则需要设置网站实际路径,且由于静态资源已经存到CDN,则缓存不再通过service worker处理
配置如下
new SWPrecacheWebpackPlugin({
dontCacheBustUrlsMatching: /\.\w{}\./,
filename: 'service-worker.js',
logger(message) {
if (message.indexOf('Total precache size is') === ) {
return;
}
if (message.indexOf('Skipping static resource') === ) {
return;
}
console.log(message);
},
navigateFallback: 'https://www.xiaohuochai.cc',
minify: true,
navigateFallbackWhitelist: [/^(?!\/__).*/],
dontCacheBustUrlsMatching: /./,
staticFileGlobsIgnorePatterns: [/\.map$/, /\.json$/],
runtimeCaching: [{
urlPattern: '/',
handler: 'networkFirst'
},
{
urlPattern: /\/(posts|categories|users|likes|comments)/,
handler: 'networkFirst'
},
]
})
]
添加到屏幕
没人愿意多此一举地在移动设备键盘上输入长长的网址。通过添加到屏幕的功能,用户可以像从应用商店安装本机应用那样,选择为其设备添加一个快捷链接,并且过程要顺畅得多
【配置项说明】
使用manifest.json文件来实现添加到屏幕的功能,下面是该文件内的配置项
short_name: 应用展示的名字
icons: 定义不同尺寸的应用图标
start_url: 定义桌面启动的 URL
description: 应用描述
display: 定义应用的显示方式,有 种显示方式,分别为:
fullscreen: 全屏
standalone: 应用
minimal-ui: 类似于应用模式,但比应用模式多一些系统导航控制元素,但又不同于浏览器模式
browser: 浏览器模式,默认值
name: 应用名称
orientation: 定义默认应用显示方向,竖屏、横屏
prefer_related_applications: 是否设置对应移动应用,默认为 false
related_applications: 获取移动应用的方式
background_color: 应用加载之前的背景色,用于应用启动时的过渡
theme_color: 定义应用默认的主题色
dir: 文字方向, 个值可选 ltr(left-to-right), rtl(right-to-left) 和 auto(浏览器判断),默认为 auto
lang: 语言
scope: 定义应用模式下的路径范围,超出范围会以浏览器方式显示
下面是一份常规的manifest.json文件的配置
{
"name": "小火柴的前端小站",
"short_name": "前端小站",
"start_url": "/",
"display": "standalone",
"description": "",
"theme_color": "#fff",
"background_color": "#d8d8d8",
"icons": [{
"src": "./logo_32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "./logo_48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "./logo_96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "./logo_144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "./logo_192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./logo_256.png",
"sizes": "256x256",
"type": "image/png"
}
]
}
【注意事项】
1、在 Chrome 上首选使用 short_name,如果存在,则优先于 name 字段使用
2、图标的类型最好是png,,且存在144px的尺寸,否则会得到如下提示
Site cannot be installed: a 144px square PNG icon is required, but no supplied icon meets this requirement
3、start_url表示项目启动路径
如果是'/',则启动路径为
localhost:/
如果是'/index.html',则启动路径为
localhost:/index.html
所以,最好填写'/'
【HTML引用】
在HTML文档中通过link标签来引用manifest.json文件
<link rel="manifest" href="/manifest.json">
要特别注意manifest文件路径问题,要将该文件放到静态资源目录下,否则,会找不到该文件,控制台显示如下提示
Manifest is not valid JSON. Line: , column: , Unexpected token
如果index.html也位于静态资源目录,则设置如下
<link rel="manifest" href="/manifest.json">
如果index.html位于根目录,而静态资源目录为static,则设置如下
<link rel="manifest" href="/static/manifest.json" />
【meta标签】
为了更好地SEO,需要通过meta标签设置theme-color
<meta name="theme-color" content="#fff"/>
【SSR】
如果是服务器端配置,需要在server.js文件中配置manifest.json、logo、icon等文件的静态路径
app.use(express.static(path.join(__dirname, 'dist')))
app.use('/manifest.json', express.static(path.join(__dirname, 'manifest.json')))
app.use('/logo', express.static(path.join(__dirname, 'logo')))
app.use('/service-worker.js', express.static(path.join(__dirname, 'dist/service-worker.js')))
网站PWA升级的更多相关文章
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- 网站 HTTP 升级 HTTPS 完全配置手册
网站 HTTP 升级 HTTPS 完全配置手册 今天,所有使用Google Chrome稳定版的用户迎来了v68正式版首个版本的发布,详细版本号为v68.0.3440.75,上一个正式版v67.0.3 ...
- 经典文摘:饿了么的 PWA 升级实践(结合Vue.js)
自 Vue.js 官方推特第一次公开到现在,我们就一直在进行着将饿了么移动端网站升级为 Progressive Web App 的工作.直到近日在 Google I/O 2017 上登台亮相,才终于算 ...
- 网站HTTP升级HTTPS完全配置手册
本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 今天,所有使用Google Chrome稳定版的用户迎来了v68正式 ...
- 网站通信协议升级到HTTPS&HTTP2
为何要升级到HTTPS和HTTP2? http://baijiahao.baidu.com/s?id=1602041305989767011&wfr=spider&for=pc htt ...
- 2018网站Https升级完全攻略
这篇文章主要讲下HTTPs升级的全部流程,包括SSL/TLS证书获取,证书安装,网站调试(将站内http资源全部改为https+重定向等),升级成功后向谷歌webmaster和GA的重新提交新的网站. ...
- CODING 静态网站服务升级,快速、稳定、高拓展!
CODING 静态网站拥有强大的页面托管服务,目前已有数万开发者.设计师.产品经理.团队与企业使用 CODING 静态网站托管了他(她)们的个人网站.博客.企业与产品官网.在线文档等.CODING 静 ...
- 自动化运维:网站svn代码上线更新(flask+saltstack)
阶段性总结: 跌跌撞撞的用了一周左右的时间做完了网站自动升级功能,中间遇到了很多的问题,也学到了很多,在此做一个总结. 1.整体架构: 后台:nginx+uwsgi #nginx提供w ...
- 为什么非全站升级HTTPS不可?
升级HTTPS已经是大势所趋,但仍有大量互联网企业犹豫是否要全站升级HTTPS,为此本文梳理了全站升级HTTPS与部分升级HTTPS的优劣势对比,来判断是否真的有必要进行全站HTTPS升级. HTTP ...
随机推荐
- springcloud情操陶冶-bootstrapContext(二)
承接前文监听器对bootstrapContext创建的引导,笔者了解到其主要入口类为BootstrapImportSelectorConfiguration.本文将基于此类进行简单的分析 Bootst ...
- 【大数据安全】基于Kerberos的大数据安全验证方案
1.背景 互联网从来就不是一个安全的地方.很多时候我们过分依赖防火墙来解决安全的问题,不幸的是,防火墙是假设"坏人"是来自外部的,而真正具有破坏性的攻击事件都是往往都是来自于内部的 ...
- SAMBA服务和FTP服务讲解(week3_day1)--技术流ken
samba服务 Smb主要作为网络通信协议; Smb是基于cs架构: 完成Linux与windows之间的共享:linux与linux之间共享用NFS 第一步:安装samba [root@ken ~] ...
- 《C#并发编程经典实例》学习笔记—2.5 等待任意一个任务完成 Task.WhenAny
问题 执行若干个任务,只需要对其中任意一个的完成进行响应.这主要用于:对一个操作进行多种独立的尝试,只要一个尝试完成,任务就算完成.例如,同时向多个 Web 服务询问股票价格,但是只关心第一个响应的. ...
- 你必须知道的.net读书笔记之第二回深入浅出关键字---对抽象编程:接口和抽象类
请记住,面向对象思想的一个最重要的原则就是:面向接口编程. 借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程. 抽象类应主要用于关系密切的对象,而接口 ...
- 开始食用grpc(之二)
开始食用grpc(之二) 转载请注明出处:https://www.cnblogs.com/funnyzpc/p/9570992.html ``` 前段时间有童鞋找我开专栏.搬家.甚至还有人找我写书的. ...
- 怎樣添加設置GridView,CheckBox全選功能
GridView內CheckBox控件全選設置 不需要添加後台代碼操作,前端即可完成設置,如下: 前端代碼: 1.設置javascript. <html xmlns="http://w ...
- iOS 类方法 、野指针与空指针
一.类方法: 不依赖于对象,执行效率更高; 能用类方法解决的问题,尽量使用类方法; 类方法中不能直接访问实例变量(成员变量) 二.野指针和空指针是什么?什么时候产生?怎么避免? 只要一个对象被释放了, ...
- Objective-C Block与函数指针比较
相似点 1.函数指针和Block都可以实现回调的操作,声明上也很相似,实现上都可以看成是一个代码片段. 2.函数指针类型和Block类型都可以作为变量和函数参数的类型.(typedef定义别名之后,这 ...
- 解决RSA加密中,System.Security.Cryptography.CryptographicException: 系统找不到指定的文件
首先说下环境,win2008R2,iis7.5 遇到这个问题,困扰了我一天,在外国的网站上找到答案,还好有点英文基础.最后算是解决了,不过其中的原理还是没有搞的十分清楚. 先说下解决办法, 打开IIS ...