关于渐进式 Web 应用,你应该知道的一切
渐进式 Web 应用是利用现代浏览器的特性,可以添加到主屏幕上,表现得像原生应用程序一样的 Web 应用程序。
什么是渐进式 Web 应用
渐进式 Web 应用(PWA)本质上与普通的网站没有什么不同 - 它也是由 HTML、CSS 和 JavaScript 组成,并且存活于浏览器中。将 PWA 与普通网站区别开的是它需要满足的 10 个核心概念列表。下面就是直接从 Google 开发者网站上摘录的这个列表:
- 安全 – 通过 HTTPS 来提供服务来防止网络窥探,保证内容不被篡改。
- 渐进式 – 能够让每一位用户使用,无论用户使用什么浏览器,因为它是始终以渐进增强为原则
- 响应式 – 适应任何环境:桌面电脑、智能手机、平板电脑,或者其他设备。
- 不依赖网络连接 – 通过用 service workers 增强,可以在离线或者低质量网络下工作
- 类原生应用 – 有像原生应用般的交互和导航给用户原生应用般的体验,因为它是建立在 app shell model 上的。
- 持续更新 – 受益于 service worker 的更新进程,应用能够始终保持更新。
- 可发现 – 可识别为“应用程序”,是得益于 W3C manifests 元数据和 service worker 的登记,让搜索引擎能够找到 web 应用。
- 可再次访问 – 通过推送通知等特性让用户再次访问变得容易。
- 可安装 – 允许用户保留对他们有用的应用在主屏幕上,不需要通过应用商店。
- 可链接 – 通过 URL 可以轻松分享应用,不用复杂的安装即可运行。
遵循这些指南,会确保你的应用不仅在浏览器中查看时,还能在单独通过主屏幕快捷键启动时,都运行的不错。你可能会发现 Google 选用的措辞令人相当困惑,不过不要着急,我们会在本教程中一个一个解释这些规则。
渐进式 Web 应用不是什么
PWA 的概念不应该与如下概念混淆:基于 Cordova 的混合 app,React Native,NativeScript,Electron 以及 NW.js...
所有前面提到的技术都是把 HTML 应用打包成可执行文件,比如.apk、.exe等等,然后必须从各自的应用商店下载下来,安装到用户的设备上。
PWA 不需要安装,也依然不能用在 Google Play 或者 iTunes 应用商店中。要下载一个 PWA,只需要访问它的网站,然后将其作为快捷键保存到主屏幕上。对 iOS 和 Android 各自开发和维护一个版本不再是问题,但是需要考虑浏览器支持不支持。
1. 安全
大多数渐进式 Web 应用要使用原生 API 和 service worker 这些处理敏感数据的技术,需要谨慎处理。这就是为什么每个 PWA 都要通过 HTTPS 连接访问的原因。
如果你没有带有 SSL 证书的服务器,那么在安全环境下运行项目的最简单的方法是通过 GitHub Pages 或者类似的服务。所有 Github 库都可以直接通过 HTTPS 存放,并且 GitHub 和 GitHub Pages 对公共仓库都是免费的。
这是我们用来存放演示应用的地方:https://tutorialzine.github.io/pwa-photobooth/。
如果只是在本地服务器上测试,还可以试试 Ngrok。它是一个小工具,可以在任何当前运行的本地主机和一个公共 URL 之间建立一个安全通道。Ngrok 是免费的,并且可用在 Windows、Mac 和 Linux 系统上。
2. 渐进式
本质上,渐进式的意思是,PWA 应该使用被广泛支持的 Web 技术,并且可以同样运行在尽可能多的浏览器上。众所周知,在 Web 开发领域,这近乎是不可能的,但是我们依然可以做一些事情来覆盖更大的用户群。
例如,在 PhotoBooth 应用程序中,我们使用 getUserMedia() API 来访问一个设备上的硬件相机。它在不同浏览器上的支持很不一致 - Safari 完全不支持,而支持它的浏览器需要前缀,并且用法各不相同。
为确保更多的人可以使用我们的应用程序,我们涵盖了所有前缀:
navigator.getMedia = (
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia
);
如果所有前缀都不行,就显示一个错误:
if (!navigator.getMedia) {
displayErrorMessage("你的浏览器不支持 navigator.getUserMedia 接口。");
}
else {
// 使用 Camera API
}
在可能的情况下,应该提供回退(Fallback)和填补(polyfill)。同样的原则也适用于 CSS 和 HTML 代码。
3. 响应式
应用程序应该在所有设备上都看起来不错,不管屏幕大小是多少。我们应用的 UI 相当简单,所以只用了两个媒体查询来控制字体大小、padding、margin 等。
不要害怕使用 CSS 库和框架,比如 Bootstrap。它们会让表单栅格、排版处理和普通的响应性变得很容易。
4. 独立于网络连接
这是很重要的一点。使用 service worker 可以让应用能在无互联网连接的情况下依然可以运行。
有些应用可以只部分缓存:UI 被缓存,并且离线可用,动态内容依然需要访问服务器。
有些应用,比如我们的 PhotoBooth 演示应用,可以全部缓存。所有源代码和资源都将被保存在本地,应用程序在离线和在线情况以完全相同的方式运行。如下是让这种奇迹得以发生的代码:
> 这是 Service Worker 的过分简化用法,在商业项目中要慎用。
首先需要创建一个 service worker JavaScript 文件,定义背后的逻辑。
sw.js
// 安装 service worker.
this.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
// 如果这些资源中有任何资源不能保存,缓存就会失败
return cache.addAll([
// 路径是相对于缓存来源,而不是应用程序的目录。
'/pwa-photobooth/',
'/pwa-photobooth/index.html',
'/pwa-photobooth/assets/css/styles.css',
'/pwa-photobooth/assets/fonts/MaterialIcons-Regular.woff2',
'/pwa-photobooth/assets/js/script.js',
'/pwa-photobooth/assets/icons/ic-face.png',
'/pwa-photobooth/assets/icons/ic-face-large.png',
'/pwa-photobooth/manifest.json'
])
.then(function() {
console.log('成功! App 离线可用!');
})
})
);
});
// 定义一个资源被请求时候会发生什么
// 对于我们的应用,我们以缓存优先的方式
self.addEventListener('fetch', function(event) {
event.respondWith(
// 试着从缓存中获取.
caches.match(event.request)
.then(function(response) {
// 如果资源没有存储在缓存中,就回退到网络
return response || fetch(event.request);
})
);
});
然后,我们需要将该 service worker 链接到 HTML。
index.html
// 注册 Service Worker.
if ('serviceWorker' in navigator) {
// 路径是相对于缓存来源,而不是应用程序的目录.
navigator.serviceWorker.register('/pwa-photobooth/sw.js')
.then(function(reg) {
console.log('Registration succeeded. Scope is ' + reg.scope);
})
.catch(function(error) {
console.error('Registration failed with ' + error);
});
}
现在,项目中的所有文件都将被保存在用户浏览器中。所有 JavaScript 变量和对象也应该尽可能保存在 localStorage 或者 IndexDB 中。
> 现在 Service Worker 在 Chrome、Firefox 和 Opera 中是被支持的。Safari 和 Edge 也正努力采用它。希望将来所有浏览器都支持它。
5. 类原生引用
在创建 PWA 时,推荐遵循一个称为应用外壳的架构的设计概念。它听起来很复杂,但是实际上可以总结为:应用被分为两个主要组件:外壳 和内容。
外壳包含了所有静态 UI 元素,比如标题、菜单、抽屉等。在缓存应用程序时,外壳应该总是保存在设备上,因为我们想让它始终可用。这样,当无互联网连接的用户打开应用程序时,就不会看到空白屏幕或者一个奔跑的恐龙 - 而是会看到缓存了的应用程序界面以及恰当的错误消息。

内容驻留在外壳内。它也可以被缓存,但是没有必要这样做,因为内容通常是动态的,会频繁发生改变,并且每个页面加载时都可能是不同的。
6. 持续更新
一旦被缓存了,PWA 会总是从本地存储加载。不过,如果以任何方式修改了 service worker sw.js,那么在下一个页面加载时,新版本就会被下载和安装。
this.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1.0.1').then(function(cache) {
// ...
})
);
});
通过使用 service worker 更新,我们可以重新下载资源,删除旧缓存,或者彻底修改 service worker 逻辑。你可以从这篇 Google 开发者文章中,学到更多有关 SW 更新过程的知识。
7. 可发现
通过给应用程序添加一个 Web Manifest,可以提供有关应用程序的各种信息,并且可以修改应用程序在用户设备上的显示方式。它允许应用程序被带自定义图标的方式保存到主屏幕上,在一个单独的浏览器窗口中启动,以及很多其它很酷的东西。
Web Manifest 是以一个简单 JSON 文件的形式出现:
manifest.json
{
"name": "Progressive Web App: PhotoBooth",
"short_name": "PhotoBooth",
"description": "Simple Progressive Web App for taking selfies.",
"icons": [{
"src": "assets/icons/ic-face.png",
"type": "image/png",
"sizes": "72x72"
}, {
"src": "assets/icons/ic-face-large.png",
"type": "image/png",
"sizes": "144x144 256x256"
}],
"start_url": "index.html",
"display": "standalone",
"background_color": "#fff",
"theme_color": "#fff",
"orientation": "portrait"
}
大多数属性是自解释的,所以我们只讲讲较为重要的一些属性。要查看完整的 Web manifest 格式,以及所有可用的字段,请到这里。
- Shortname – 这是应用保存到主屏幕上时的名称。
- Icons – 不同分辨率的图标数组。
- Display – 定义应用打开的方式。我们选择的是独立(standalone),所以启动 PhoneBooth 时,会以全屏窗口出现,没有浏览器导航栏或者菜单。它还会被看作为多任务中的一个单独的应用。
要注册 Manifest 文件,必须把它链接到 HTML 中:
<link rel="manifest" href="manifest.json">
Safari 还不支持 Web Manifest 标准,但是我们可以用如下的苹果特定的 meta 标记,定义类原生应用的行为:
<meta name=”apple-mobile-web-app-capable” content=”yes”>
8. 可再次访问
通知推送不再只限于原生应用。多亏了 service worker 和 Push API,Web 应用程序也可以发送消息给 Android 通知栏。并不是所有应用都可以从这个功能受益,但是当正确使用此功能时,通知确实可以帮助吸引用户。
这个主题已经超出了本教程的范围,因为推送很复杂,值得用一个完整的课程讲解。如果你依然想在你的 Web 应用中实现通知推送,这里有一些最好的学习资源:
- Google 开发者网站上的《推送通知:及时、相关和准确》 – 这里.
- Google 开发者网站上的《开放 Web 上的推送通知 – 这里.
- MDN 上的《使用 Push API》 – 这里.
- Push.js 库,提供处理推送通知的更清洁的 API – 这里.
办公资源网址导航 https://www.wode007.com
9. 可安装
默认情况下,任何网站都可以用 Chrome 浏览器菜单的 "添加到主屏幕" 按钮,保存到主屏幕上。不过,让用户以这种方式 "安装" 应用程序可能有点难,因为大多数人完全不知道这个功能。
值得庆幸的是,还是有一种方式让应用程序提示用户保存它,即采用一个简单安装弹出窗口来提示。为防止开发者滥用这些弹出窗口,不允许以编程的方式显示它们。而是在应用程序满足如下几个条件时,才会让这些窗口自己出现:
- 有一个有效的 Web Manifest。
- 安装有有效的 Service Worker。
- 通过 HTTPS 访问应用程序。
我们满足上面涉及的所有条件,所以当用户访问网站几次后,会得到这个提示:

整个应用程序的安装过程就在这个简单的提示中。安装立即发生,并且一旦保存了,PhotoBooth 就可以从主屏幕图标启动,表现得与原生应用一模一样。
10. 可链接
任何人只有要浏览器,就可以访问 PWA 应用,这样应用仅通过其 URL 就可以被共享。发现或者安装这些应用不需要第三方工具。
如果应用程序以独立模式运行,因为浏览器地址栏和菜单都是不可见的,所以在应用内添加一个共享按钮也是明智的。
关于渐进式 Web 应用,你应该知道的一切的更多相关文章
- 使用 React.js 的渐进式 Web 应用程序:第 1 部分 - 介绍
使用 React.js 的渐进式 Web 应用程序:第 1 部分 - 介绍 使用 React.js 的渐进式 Web 应用程序:第 1 部分 - 介绍 来自译者 markzhai:大家也知道最近 ...
- 创建一个离线优先,数据驱动的渐进式 Web 应用程序
原文地址:Build an offline-first, data-driven PWA 译文出自:我的个人博客 概述 在本文中,您将学习如何使用 Workbox 和 IndexedDB 创建离线优先 ...
- 渐进式Web应用(PWA)入门教程(上)
最近关于渐进式Web应用有好多讨论,有一些人还在质疑渐进式Web应用是否就是移动端未来. 但在这篇文章中我并不会将渐进式APP和原生的APP进行比较,但有一点是可以肯定的,这两种APP的目标都是使用户 ...
- 渐进式Web应用(PWA)入门教程(下)
上篇文章我们对渐进式Web应用(PWA)做了一些基本的介绍. 渐进式Web应用(PWA)入门教程(上) 在这一节中,我们将介绍PWA的原理是什么,它是如何开始工作的. 第一步:使用HTTPS 渐进式W ...
- 渐进式Web应用程序的深入概述
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://www.grapecity.com.cn/blogs/wijmo-depth-ove ...
- PWA 渐进式Web应用程序 - 解释
想象一下,如果一个网站上所有的功能都能够作为一个移动应用程序为用户所用——任何设备上都可以使用.可接收所有的通知.离线模式可用,为了实现这个愿景,2015年,谷歌创造了渐进式Web应用程序(PWA). ...
- (转)PWA(Progressive Web App)渐进式Web应用程序
PWA 编辑 讨论 PWA(Progressive Web App)是一种理念,使用多种技术来增强web app的功能,可以让网站的体验变得更好,能够模拟一些原生功能,比如通知推送.在移动端利用标准化 ...
- 渐进式web应用开发---service worker 原理及介绍(一)
渐进式web应用(progressive Web app) 是现代web应用的一种新形式.它利用了最新的web功能,结合了原生移动应用的独特特性与web的优点,为用户带来了新的体验. 一:传统web端 ...
- 渐进式web应用开发-- 使用后台同步保证离线功能(六)
_ 阅读目录 一:什么是后台同步保证离线功能呢? 二:后台同步是如何实现的呢? 三:如何给sync事件传递数据? 四:在我们的项目中添加后台同步功能 回到顶部 一:什么是后台同步保证离线功能呢? 在我 ...
- Google_PWA_ServiceWork_渐进式 Web 应用_给应用提供离线体验
前言:今天结识了google PWA提供的一个对移动端Web应用提供离线体验的一个功能,感觉很有用.我这里不分享自己的写法和代码.官网文档说的很详细,直接粘过来大家看吧. 推荐官网地址:你的第一个渐进 ...
随机推荐
- Java实现 蓝桥杯 算法提高金属采集
问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫它节点好了.一些节点之间有道路相连,所有的节点和道路形成了一棵树.一共有 n 个节点,这些节点被编号为 1~n .人类将 ...
- Java实现三人年龄
2 三人年龄 三个神秘蒙面人来访F博士. 博士询问他们年龄时,他们说:我们中年龄最小的不超过19岁.我们3人年龄总和为70岁.且我们三人年龄的乘积是所有可能情况中最大的. 请帮助F博士计算他们的年龄, ...
- unittest单元测试框架入门及应用
一.简介 unittest是Python单元测试框架.unittest它支持自动化测试,在测试中使用setup(初始化)和shutdown(关闭销毁)操作,组织测试 用例为套件(批量运行),以及把测试 ...
- .NET 技术栈 思维导图
背景介绍 根据网上招聘网站的一些.NET技能需求,画了一个图,便于在自修和学习的过程当中有一个方向. 技能栈 Web front-end o 框架技术 ▣ Vue ▣ Bootstrap ▣ LayU ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 2020/06/06 JavaScript高级程序设计 面向对象的程序设计
ECMAScript虽然是一种面向对象的语言,但是他没有类的概念.所以他的对象也与其他语言中的对象有所不同. ECMA-262定义对象:一组没有特定顺序的值. 6.1 理解对象 创建对象的方法: 1. ...
- hadoop知识整理(5)之kafka
一.简介 来自官网介绍: 翻译:kafka,是一个分布式的流处理平台.LinkedIn公司开发.scala语言编写. 1.支持流处理的发布订阅模式,类似一个消息队列系统: 2.多备份存储,副本冗余 ...
- 【华为云技术分享】数据库开发:MySQL Seconds_Behind_Master简要分析
[摘要]对于mysql主备实例,seconds_behind_master是衡量master与slave之间延时的一个重要参数.通过在slave上执行"show slave status;& ...
- [AGC043-D]Merge Triplets
题目 点这里看题目. 分析 我们不妨来考虑一下生成的序列有什么性质. 为了方便表示,我们将序列\(S\)的第\(i\)项写为\(S[i]\). 首先考虑如果所有的\(A\)序列都是递增 ...
- Ubuntu安装Vmware Tools解决屏幕比例失调
前言 安装ubuntu虚拟机时默认比例如下图,且ubuntu系统选项中没有合适的比例,可以安装Vmware Tools来解决. 注意:该方法只适用于有操作界面的系统,之前有位小伙伴在服务器上也想安装T ...