Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWA浅析 #1

Open
Chance722 opened this issue Aug 28, 2019 · 0 comments
Open

PWA浅析 #1

Chance722 opened this issue Aug 28, 2019 · 0 comments
Labels
pwa pwa相关文章

Comments

@Chance722
Copy link
Owner

Chance722 commented Aug 28, 2019

PWA浅析

PWAGoogle2016 年开始推广的项目,这几年的发展一直也是不温不火。但是不得不否认,PWA 对提升 Web 应用的安全、性能和体验有着很大的意义,非常值得我们去了解与学习。本文将从以下几个方面对 PWA 这项应用技术进行解析,并适当地抛出一些问题。希望各位看官在能再进一步学习之前,对 PWA 能有个较为全面的了解。废话不多说,直接上菜~ 🍲

简要

  • ✅什么是PWA?
  • ✅PWA技术清单预览
  • ✅PWA实际应用的一些思考
  • ✅小结

正文

⭐ 什么是PWA?

PWA,全称 Progressive Web App, 翻译过来即是渐进式网页应用。在对其做介绍之前,不妨先贴上维基百科和MDN上的定义:

Wiki

渐进式网络应用程序(英语:Progressive Web Apps,简称:PWA)是一种普通网页或网站架构起来的网络应用程序,但它可以以传统应用程序或原生移动应用程序形式展示给用户。这种应用程序形态视图将目前最为现代化的浏览器提供的功能与移动设备的体验优势相结合。

MDN

PWA(Progressive web apps,渐进式 Web 应用)运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序。

通过上面的定义我们注意到几个关键字:渐进式普通网页原生应用Web API 等等。很明显的,PWA 本质还是我们的网页应用,它并不是特指某项技术,它是一个涵盖性术语,是一系列现代 Web 技术的组合,其主要目的是为了在网页应用中实现与原生应用相近的用户体验。

👉 抛出问题1,怎样理解渐进式?

在我看来渐进式可以从两个方面去看待:面向用户,是向下兼容和渐进增强的。渐进式应用必须保证的一个前提点就是所有人都能访问这个页面,在这个前提条件下,再去允许部分人享受更先进的一个页面版本。面向开发者,渐进式应用应该是跟随浏览器标准的制定及自身网站的条件逐步去完善优化的,并不是一蹴而就的过程。

⭐ PWA技术清单预览

接下来继续让我们看下这套技术清单主要包括哪些:

  • Service Worker
  • Web App Manifest
  • Push&Notifications
  • Background Sync
  • ...

下面针对这套组合拳逐一介绍下

Service Worker

  • 简介:PWA 核心部分,是一项比较新的 Web 技术,旨在提高 WebApp 的离线缓存能力。Service Worker 顾名思义,翻译过来就是服务工人,是服务于前端页面的后台线程,基于 Web Worker 实现。有着独立的 js 运行环境,分担、协助前端页面完成前端开发者分配给后台执行的任务。基于它可以实现拦截和处理网络请求、消息推送、静默更新、事件同步等服务。

👉 抛出问题2,Web Worker 是什么?和 Service Worker 又是什么关系?

Web Worker 是 HTML5 标准的一部分,同样也允许一段 JavaScript 程序运行在主线程之外的另外一个线程中,在主线程执行任务的同时, worker 线程也可以在后台执行它自己的任务。而 Service Worker,可以说是 Web Worker 进一步发展的产物。对比Web Worker,它不是服务于某个特定页面的,而是服务于多个页面的(按照同源策略)。其次,Service Worker 会常驻在浏览器中,即使页面关闭,Service Worker 也不会停止,除非主动终结或者被浏览器回收,这个线程才会结束。
  • 特点

    • 一个独立的 worker 线程,独立于当前网页进程,有自己独立的 worker context
    • 一旦被 install,就永远存在,除非被手动 unregister
    • 用到的时候可以直接唤醒,不用的时候自动睡眠
    • 可编程拦截代理请求和返回,缓存文件,缓存的文件可以被网页进程取到(包括网络离线状态)
    • 离线内容开发者可控
    • 能向客户端推送消息
    • 不能直接操作 DOM
    • 必须在 HTTPS 环境下才能工作
    • 异步实现,内部大都是通过 Promise 实现
  • 工作原理

    1. 主线程成功注册 Service Worker 之后,开始下载并解析执行 Service Worker 文件,同时触发 worker 线程的 install 事件。
    2. 如果 install 事件回调成功执行,则开始激活 Service Worker, 同时触发 worker 线程的 activate 事件,如果 install 事件回调执行失败,则生命周期进入 Error 终结状态,终止生命周期。
    3. 完成激活之后,Service Worker 就能够控制作用域下的页面资源请求,监听 fetch 事件。
    4. 如果激活后 Service Workerunregister 或者有新的 Service Worker 版本更新,则当前 Service Worker 生命周期完结,进入 Terminated 终结状态。

👉 抛出问题3,Service Worker 更新机制是怎样的?需要注意哪些点?

首先需要知道的一个点是 Service Worker 的安装和更新都是独立的进程,它的更新是由浏览器触发的。Service Worker 控制着整个 APP 的离线缓存,为了避免 Service Worker 缓存自己导致死锁无法升级,通常 sw.js 本身的缓存是直接交给 HTTP 服务器缓存的。所以这里就需要我们注意两个点:一是不要给 service-worker.js 设置不同的名字,二是不要给 service-worker.js 设置缓存。
  • 兼容性

    至少还是绿了一片了,很好。😉

Web App Manifest

  • 简介:Web App Manifest 是指一个以 JSON 格式存储的 Web 应用程序清单,提供有关应用程序的信息(如名称,作者,图标和描述等)。其目的是将 Web 应用程序安装到设备的主屏幕,为用户提供更快的访问和更丰富的体验。

一个 manifest.json 的内容会像如下, 这里需要注意的是添加到主屏幕时在 Android 设备至少需要提供 192 像素以上的图标才会显示。

{
  "short_name": "",
  "name": "",
  "icons": [
    { "src": "", "type": "", "sizes": "" }
  ],
  "start_url": "",
  "background_color": "",
  "display": "",
  "scope": "",
  "theme_color": "",
  "description": ""
}
  • 兼容性

    乍看之下还是比较惨烈,我们只看 Chrome 就好。🤕

Push&Notifications

  • 简介: Push API 赋予了客户端页面从第三方服务器接受消息通知的能力,而 Notifications API 则主要用于向用户展示桌面通知。通过这对 API 我们可以轻松实现消息的推送与通知。

  • Push实现原理

    在Push中有三个登场角色,分别是:

    • 浏览器: 就是我们的客户端

    • Push Service: 专门的Push服务,你可以认为是一个第三方服务,目前 chromefirefox 都有自己的 Push Service。理论上只要浏览器支持,可以使用任意的 Push Service

    • 后端服务: 指我们自己的后端服务

      推送流程图如下:(来自Web Push协议草案

      结合时序图的各个步骤,我们可以将其分为订阅(subscribe)与推送(push)两部分来看。

    • subscribe,首先是订阅:

      1. Ask Permission:这一步不再上图的流程中,这其实是浏览器中的策略。浏览器会询问用户是否允许通知,只有在用户允许后,才能进行后面的操作。
      2. Subscribe:浏览器(客户端)需要向Push Service发起订阅(subscribe),订阅后会得到一个PushSubscription对象
      3. Monitor:订阅操作会和Push Service进行通信,生成相应的订阅信息,Push Service会维护相应信息,并基于此保持与客户端的联系;
      4. Distribute Push Resource:浏览器订阅完成后,会获取订阅的相关信息(存在于PushSubscription对象中),我们需要将这些信息发送到自己的服务端,在服务端进行保存。
    • Push Message,然后是推送:

      1. Push Message阶段一:我们的服务端需要推送消息时,不直接和客户端交互,而是通过Web Push协议,将相关信息通知Push Service;
      2. Push Message阶段二:Push Service收到消息,通过校验后,基于其维护的客户端信息,将消息推送给订阅了的客户端;
      3. 最后,客户端收到消息,完成整个推送过程。

👉 抛出问题4,Push Service 是什么?

A push service receives a network request, validates it and delivers a push message to the appropriate browser.

Push Service 可以接收网络请求,校验该请求并将其推送给合适的浏览器客户端。Push Service 还有一个非常重要的功能:当用户离线时,可以帮我们保存消息队列,直到用户联网后再发送给他们。

目前,不同的浏览器厂商使用了不同的 Push Service。例如,chrome 使用了 google 自家的 FCM(前身为GCM),firefox 也是使用自家的服务。那么我们是否需要写不同的代码来兼容不同的浏览器所使用的服务呢?答案是并不用。Push Service 遵循 Web Push Protocol,其规定了请求及其处理的各种细节,这就保证了,不同的 Push Service也会具有标准的调用方式。
  • 兼容性

     

    兼容性较好的浏览器还是主要集中 Chrome, FireFox, Edge 这些,但是对比兼容性更头疼的一个点还是接收推送在国内必须得翻墙这个点。😭

Background Sync

  • 简介:Background Sync (后台同步功能) 是指通过 Service WorkerSyncManage 实现延迟用户行为,直到用户网络连接稳定后再重新执行请求操作的一个功能。

  • 工作原理:

    1. Service Worker 中监听 sync 事件
    2. 在浏览器中发起后台同步 sync, 主要用到 registration.sync.register() 方法
    3. 触发 Service Workersync 事件,在该监听回调中进行相关操作,例如向后端发起请求
    4. 最后,可以在 Service Worker 中对服务端返回的数据进行处理

👉 抛出问题5,为什么断网了 Service Worker 仍能维持请求?在处理数据过程中Service Worker 和前端页面是怎么交互的?

断网后 Service Worker 之所以可以维持请求主要取决于两个点,一是 Service Worker 常驻浏览器的特点,并不会因为页面关闭或者断开网络等原因导致停止。二是 Service Worker 监听 sync 事件返回的事件对象拥有方法 waitUntil() 扩展了事件的生命周期,所以将 Promise 对象放在 e.waitUntil() 内可以确保用户离开网站后,Service Worker 会持续在后台运行,等待该请求完成。在 Service Worker 进行后台请求,就免不了跟前端进行数据交互,而在浏览器主线程和 Web Worker 线程之间,我们可以通过 postMessage 来进行通信。
  • 兼容性

    唔... sync API 基本还是只有 Google 自家的 Chrome 可用 😷

当然,PWA 并不局限于上述几个特性,除此之外还有诸如 Cache API 缓存、App Shell 和骨架屏等等各种可以扩展的方面,文章主要列举了比较核心的几个特性进行解析。

⭐ PWA实际应用的一些思考

待补充

参考链接

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pwa pwa相关文章
Projects
None yet
Development

No branches or pull requests

1 participant