前面的话

  渐进式网络应用 ( 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. 获得当前EIP的值

    VS2017 内联汇编 __asm { call NEXT NEXT: pop eax }

  2. 痞子衡嵌入式:开启NXP-MCUBootUtility工具的HAB签名功能 - CST(中英双语)

    1 Reason for enabling HAB signature function 为什么要开启HAB签名功能 NXP-MCUBootUtility is a tool designed for ...

  3. Linux系列

    Linux入门及进阶学习. 目录 Linux的安装 GNOME图形界面的基本操作 命令行BASH的基本操作 Linux文件系统的基本结构 Linux文件基本操作管理 Linux系统目录架构 Linux ...

  4. Spring 中 IoC 容器简介

    IoC 是一种通过描述来生成或者获取对象的技术,可以说 Spring 是一种基于 IoC 容器编程的框架 在一个系统中可以生成各种对象,并且这些对象都需要进行管理.为了描述这些对象关系,我们需要一个容 ...

  5. js循环语句

    1.for循环 for(语句1:语句2:语句3){ 代码块 } //语句1:初始化表达式; //语句2:条件表达式; //语句3:更新表达式; 2.for-in循环 for(x in object){ ...

  6. MySQL字段操作与数据处理

    一,对字段的操作 1.拼接字段:Concat()函数 多数DBMS使用 + 或者 || 来实现拼接,而MySQL使用 Concat() 函数来实现拼接. 实例: Concat()函数拼接时加上的字符需 ...

  7. 字符串转数字练习--String to Integer (atoi)

    Implement atoi which converts a string to an integer. The function first discards as many whitespace ...

  8. Mac Git 安装和配置

    一.git下载与安装 点击Git,然后选择下载安装包 git --version,终端输入该命令, 如输出版本号,则说明安装成功. git version 2.20.1 二.git基本配置 通过下面这 ...

  9. 简单shellcode编写

    0x00 介绍 Shellcode 是指经过精心设计的一串指令,一旦注入正在运行的应用程序中即可运行,常用于栈和基于堆的溢出.术语Shellcode意思指的便是用于启动一个命令Shell的已编写好的可 ...

  10. Excel自定义公式,类似VLOOKUP的查询

    Excel在使用VLOOKUP时,当检索值超过255长度的时候就会报错,没法正常检索. 官方提供的办法是通过INDEX和MATCH公式组合使用来解决. 微软官方方案 1,公式 =INDEX($A$5: ...