前面的话

  渐进式网络应用 ( 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升级的更多相关文章

  1. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  2. 网站 HTTP 升级 HTTPS 完全配置手册

    网站 HTTP 升级 HTTPS 完全配置手册 今天,所有使用Google Chrome稳定版的用户迎来了v68正式版首个版本的发布,详细版本号为v68.0.3440.75,上一个正式版v67.0.3 ...

  3. 经典文摘:饿了么的 PWA 升级实践(结合Vue.js)

    自 Vue.js 官方推特第一次公开到现在,我们就一直在进行着将饿了么移动端网站升级为 Progressive Web App 的工作.直到近日在 Google I/O 2017 上登台亮相,才终于算 ...

  4. 网站HTTP升级HTTPS完全配置手册

    本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 今天,所有使用Google Chrome稳定版的用户迎来了v68正式 ...

  5. 网站通信协议升级到HTTPS&HTTP2

    为何要升级到HTTPS和HTTP2? http://baijiahao.baidu.com/s?id=1602041305989767011&wfr=spider&for=pc htt ...

  6. 2018网站Https升级完全攻略

    这篇文章主要讲下HTTPs升级的全部流程,包括SSL/TLS证书获取,证书安装,网站调试(将站内http资源全部改为https+重定向等),升级成功后向谷歌webmaster和GA的重新提交新的网站. ...

  7. CODING 静态网站服务升级,快速、稳定、高拓展!

    CODING 静态网站拥有强大的页面托管服务,目前已有数万开发者.设计师.产品经理.团队与企业使用 CODING 静态网站托管了他(她)们的个人网站.博客.企业与产品官网.在线文档等.CODING 静 ...

  8. 自动化运维:网站svn代码上线更新(flask+saltstack)

    阶段性总结:      跌跌撞撞的用了一周左右的时间做完了网站自动升级功能,中间遇到了很多的问题,也学到了很多,在此做一个总结.   1.整体架构: 后台:nginx+uwsgi  #nginx提供w ...

  9. 为什么非全站升级HTTPS不可?

    升级HTTPS已经是大势所趋,但仍有大量互联网企业犹豫是否要全站升级HTTPS,为此本文梳理了全站升级HTTPS与部分升级HTTPS的优劣势对比,来判断是否真的有必要进行全站HTTPS升级. HTTP ...

随机推荐

  1. Cortex-M 实现互斥操作的三种方法

    注:本文仅针对Cortex-M3/4 系列进行讲述. 在传统的ARM处理器架构中,常使用SWP指令来实现锁的读/写原子操作,但从ARM v6开始,读/写访问在独立的两条总线上进行,SWP指令已无法在此 ...

  2. 使用JsonProperty Attribute修改返回json

    使用JsonProperty Attribute修改返回 json 值的name 本例使用JsonPropertyAttribute在序列化为JSON时更改属性的名称. public class Vi ...

  3. 论AOP面向切面编程思想

    原创: eleven 原文:https://mp.weixin.qq.com/s/8klfhCkagOxlF1R0qfZsgg [前言] AOP(Aspect-Oriented Programming ...

  4. C# 默认访问权限

    声明类.方法.字段.属性时不加访问权限修饰符时的访问权限是什么呢?1. 声明命名空间.类,前面不加限制访问修饰符时,默认访问权限为internal——访问仅限于当前程序集. 2. 声明类成员(域.属性 ...

  5. JVM的总结

    1.JVM的内存模型 JVM主要由程序计数器,虚拟机栈,堆,方法区,本地方法区 1.程序计数器的功能是记录当前线程执行到了字节码文件的哪一行, JVM执行的是.java编译后的.class文件 2.虚 ...

  6. linux下载服务器上的文件命令-sz

    语法:sz  文件 比如要下载下面这个com.zip这个压缩包 输入sz com.zip 弹出下载页面,即可开始下载文件

  7. 吐血bug-- 多个input框接连blur事件导致alert接连弹出

    本来今天想记录一下Flow在vue源码中的应用,结果临时触发了个bug... bug描述: elementUi + Vue 技术 需求:一个表格中有至少两条数据,每条数据都有input框,在失去焦点后 ...

  8. 【设计模式】适配器模式 Adapter Pattern

    适配器模式在软件开发界使用及其广泛,在工业界,现实中也是屡见不鲜.比如手机充电器,笔记本充电器,广播接收器,电视接收器等等.都是适配器. 适配器主要作用是让本来不兼容的两个事物兼容和谐的一起工作.比如 ...

  9. ElasticSearch-6.3.2 linux 安装

    在linux 系统安装ElasticSearch-6.3.2最新版本,也适合6.x 系列版本做参考 前提先在linux 安装好jdk1.8 创建用户 从5.0开始,ElasticSearch 安全级别 ...

  10. 27号华为笔试(三道ac两道)

    三道题目case:100,100,0: 三个题目: 前两个都全部ac了,第三题没时间: 记录一下大概的思路: 第一题 主要通过Java中的字符串处理函数:然后控制字符串输入格式: 卡bug的点: 1: ...