前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版

浅谈PWA(Progressive Web App)

首页2018-09-04 18:00:43Front-End
JavaScriptPWA

# 一、初识PWA

  • PWA,即Progressive Web App, 是提升 Web App 的体验的一种新方法,能给用户原生应用的体验。
  • 一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能

# 1.1 PWA中的一些技术

PWA本身其实是一个概念集合,它不是指某一项技术,而是通过一系列的Web技术与Web标准来优化Web App的安全、性能和体验。其中涉及到的一些技术概念包括了

  • Web App Manifest
  • Service Worker
  • Cache API 缓存
  • Push、Notification 推送与通知
  • Background Sync后台同步
  • 响应式设计

# 1.2 解决了哪些问题

  • 可以添加至主屏幕,点击主屏幕图标可以实现启动动画以及隐藏地址栏
  • 实现离线缓存功能,即使用户手机没有网络,依然可以使用一些离线功能
  • 实现了消息推送

# 1.3 PWA存在的问题

  • 支持率不高:现在ios手机端不支持pwa,IE也暂时不支持 Chrome在中国桌面版占有率还是不错的,安卓移动端上的占有率却很低
  • 各大厂商还未明确支持pwa
  • 依赖的GCM服务在国内无法使用
  • 微信小程序的竞争

尽管有上述的一些缺点,PWA技术仍然有很多可以使用的点。

  • service worker技术实现离线缓存,可以将一些不经常更改的静态文件放到缓存中,提升用户体验。
  • service worker实现消息推送,使用浏览器推送功能,吸引用户 渐进式开发,尽管一些浏览器暂时不支持,可以利用上述技术给使用支持浏览器的用户带来更好的体验

# 二、PWA的实现

# 2.1 Manifest实现添加至主屏幕

<!--index.html-->

<head>
  <title>Minimal PWA</title>
  <meta name="viewport" content="width=device-width, user-scalable=no" />
  <link rel="manifest" href="manifest.json" />
  <link rel="stylesheet" type="text/css" href="main.css">
  <link rel="icon" href="/e.png" type="image/png" />
</head>
@前端进阶之旅: 代码已经复制到剪贴板
// manifest.json

{
  "name": "Minimal PWA", // 必填 显示的插件名称
  "short_name": "PWA Demo", // 可选  在APP launcher和新的tab页显示,如果没有设置,则使用name
  "description": "The app that helps you understand PWA", //用于描述应用
  "display": "standalone", // 定义开发人员对Web应用程序的首选显示模式。standalone模式会有单独的
  "start_url": "/", // 应用启动时的url
  "theme_color": "#313131", // 桌面图标的背景色
  "background_color": "#313131", // 为web应用程序预定义的背景颜色。在启动web应用程序和加载应用程序的内容之间创建了一个平滑的过渡。
  "icons": [ // 桌面图标,是一个数组
    {
    "src": "icon/lowres.webp",
    "sizes": "48x48",  // 以空格分隔的图片尺寸
    "type": "image/webp"  // 帮助userAgent快速排除不支持的类型
  },
  {
    "src": "icon/lowres",
    "sizes": "48x48"
  },
  {
    "src": "icon/hd_hi.ico",
    "sizes": "72x72 96x96 128x128 256x256"
  },
  {
    "src": "icon/hd_hi.svg",
    "sizes": "72x72"
  }
  ]
}
@前端进阶之旅: 代码已经复制到剪贴板
  • Manifest参考文档: https://developer.mozilla.org/zh-CN/docs/Web/Manifest
  • 如果用的是安卓手机,可以下载chrome浏览器自己操作看看

# 2.2 service worker实现离线缓存

# 2.2.1 什么是service worker

Service Worker 是 Chrome 团队提出和力推的一个 WEB API,用于给 web 应用提供高级的可持续的后台处理能力

Service Workers 就像介于服务器和网页之间的拦截器,能够拦截进出的HTTP 请求,从而完全控制你的网站

# 2.2.2 最主要的特点

  • 在页面中注册并安装成功后,运行于浏览器后台,不受页面刷新的影响,可以监听和截拦作用域范围内所有页面的 HTTP 请求。
  • 网站必须使用 HTTPS。除了使用本地开发环境调试时(如域名使用 localhost)
  • 运行于浏览器后台,可以控制打开的作用域范围下所有的页面请求
  • 单独的作用域范围,单独的运行环境和执行线程
  • 不能操作页面 DOM。但可以通过事件机制来处理
  • 事件驱动型服务线程

为什么要求网站必须是HTTPS的,大概是因为service worker权限太大能拦截所有页面的请求,如果http的网站安装service worker很容易被攻击

# 2.2.3 生命周期

当用户首次导航至 URL 时,服务器会返回响应的网页。

  • 第1步:当你调用 register() 函数时, Service Worker 开始下载。
  • 第2步:在注册过程中,浏览器会下载、解析并执行 Service Worker ()。如果在此步骤中出现任何错误,register() 返回的 promise 都会执行 reject 操作,并且 Service Worker 会被废弃。
  • 第3步:一旦 Service Worker 成功执行了,install 事件就会激活
  • 第4步:安装完成,Service Worker 便会激活,并控制在其范围内的一切。如果生命周期中的所有事件都成功了,Service Worker 便已准备就绪,随时可以使用了!

chrome://serviceworker-internals 来了解当前浏览器中所有已安装Service Worker的详细情况

# 2.2.4 实现离线缓存

HTTP缓存

  • Web 服务器可以使用 Expires 首部来通知 Web客户端,它可以使用资源的当前副本,直到指定的“过期时间”。反过来,浏览器可以缓存此资源,并且只有在有效期满后才会再次检查新版本。使用 HTTP 缓存意味着你要依赖服务器来告诉你何时缓存资源和何时过期

service worker缓存

  • Service Workers 的强大在于它们拦截 HTTP 请求的能力 进入任何传入的 HTTP 请求,并决定想要如何响应。在你的 Service Worker 中,可以编写逻辑来决定想要缓存的资源,以及需要满足什么条件和资源需要缓存多久。一切尽归你掌控!
<!--index.html-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello Caching World!</title>
  </head>
  <body>
    <!-- Image -->
    <img src="/images/hello.png" />                 
    <!-- JavaScript -->
    <script async src="/js/script.js"></script>     
    <script>
      // 注册 service worker
      if ('serviceWorker' in navigator) {           
        navigator.serviceWorker.register('/service-worker.js', {scope: '/'}).then(function (registration) {
          // 注册成功
          console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }).catch(function (err) {                   
          // 注册失败 :(
          console.log('ServiceWorker registration failed: ', err);
        });
      }
    </script>
  </body>
</html>
@前端进阶之旅: 代码已经复制到剪贴板
  • 注:Service Worker 的注册路径决定了其 scope 默认作用页面的范围。
  • 如果 service-worker.js 是在 /sw/ 页面路径下,这使得该 Service Worker 默认只会收到 页面/sw/ 路径下的 fetch 事件。
  • 如果存放在网站的根路径下,则将会收到该网站的所有 fetch 事件。
  • 如果希望改变它的作用域,可在第二个参数设置 scope 范围。示例中将其改为了根目录,即对整个站点生效。
// service-worker.js

var cacheName = 'helloWorld';     // 缓存的名称  
// install 事件,它发生在浏览器安装并注册 Service Worker 时        
self.addEventListener('install', event => { 
/* event.waitUtil 用于在安装成功之前执行一些预装逻辑
 但是建议只做一些轻量级和非常重要资源的缓存,减少安装失败的概率
 安装成功后 ServiceWorker 状态会从 installing 变为 installed */
  event.waitUntil(
    caches.open(cacheName)                  
    .then(cache => cache.addAll([    // 如果所有的文件都成功缓存了,便会安装完成。如果任何文件下载失败了,那么安装过程也会随之失败。        
      '/js/script.js',
      '/images/hello.png'
    ]))
  );
});
  
/**
为 fetch 事件添加一个事件监听器。接下来,使用 caches.match() 函数来检查传入的请求 URL 是否匹配当前缓存中存在的任何内容。如果存在的话,返回缓存的资源。
如果资源并不存在于缓存当中,通过网络来获取资源,并将获取到的资源添加到缓存中。
*/
self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request)                  
    .then(function (response) {
      if (response) {                            
        return response;                         
      }
      var requestToCache = event.request.clone();  //          
      return fetch(requestToCache).then(                   
        function (response) {
          if (!response || response.status !== 200) {      
            return response;
          }
          var responseToCache = response.clone();          
          caches.open(cacheName)                           
            .then(function (cache) {
              cache.put(requestToCache, responseToCache);  
            });
          return response;             
    })
  );
});
@前端进阶之旅: 代码已经复制到剪贴板
fe
  • 一、初识PWA
    • 1.1 PWA中的一些技术
    • 1.2 解决了哪些问题
    • 1.3 PWA存在的问题
  • 二、PWA的实现
    • 2.1 Manifest实现添加至主屏幕
    • 2.2 service worker实现离线缓存
      • 2.2.1 什么是service worker
      • 2.2.2 最主要的特点
      • 2.2.3 生命周期
      • 2.2.4 实现离线缓存
      • 2.2.5 调试相关
    • 2.3 serice worker实现消息推送
  • 三、参考

← Dva实践总结,从五个 API 到 model 数据流落地webpack4 定制前端开发环境,从零搭一套构建流水线 →