热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入浅出PWA

PWA全称为ProgressiveWebApp,中文译为渐进式WebAPP。PWA本质上是Web应用,使用现代API构建和增强,以提供增强

PWA 全称为 Progressive Web App,中文译为渐进式 Web APP。PWA本质上是 Web 应用,使用现代 API 构建和增强,以提供增强的功能、可靠性和可安装性,同时只需一个代码库就可以借助任何设备触及任何用户、任何地方,实现与原生 App 相近的用户体验。

一个 PWA 首先是一个网页, 可以通过 Web 技术编写出一个网页应用,随后添加上 App Manifest 实现添加至设备主屏幕, 通过 Service Worker 来实现离线缓存和消息推送等功能。


Web Application Manifest

Web Application Manifest,即通过一个清单文件向浏览器暴露 web 应用的元数据,包括名称、icon 的 URL 等,以备浏览器使用,比如在添加至主屏或推送通知时暴露给操作系统,从而增强 web 应用与操作系统的集成能力。

一个典型的 manifest.json:

/** 属性含义详解: https://developer.mozilla.org/zh-CN/docs/Web/Manifest */
{"lang": "en","dir": "ltr","name": "Super Racer 3000","short_name": "Racer3K","icons": [{"src": "icon/lowres.webp","sizes": "64x64","type": "image/webp"}, {"src": "icon/lowres.png","sizes": "64x64"}, {"src": "icon/hd_hi","sizes": "128x128"}],"scope": "/","id": "superracer","start_url": "/start.html","display": "fullscreen","orientation": "landscape","theme_color": "aliceblue","background_color": "red"
}

通过对 manifest.json 进行相应配置,可以实现以下功能:


Service Worker

Service Worker 是一个可编程的 Web Worker,它就像一个位于浏览器与网络之间的客户端代理,可以拦截、处理、响应流经的 HTTP 请求;配合随之引入 Cache Storage API,可以自由管理 HTTP 请求文件粒度的缓存,这使得 Service Worker 可以从缓存中向 web 应用提供资源,即使是在离线的环境下。

Service workers 主要是提供详细的浏览器和网络/缓存间的代理服务,如下图所以:

Service workers 的生命周期:

HTTP 缓存与 Service Worker 缓存 的区别:


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

  • Service Workers 的强大在于它们拦截 HTTP 请求的能力,接受任何传入的 HTTP 请求,并决定想要如何响应。在你的 Service Worker 中,可以编写逻辑来决定想要缓存的资源,以及需要满足什么条件和资源需要缓存多久。一切尽归你掌控!(所以,出于安全考虑,Service Workers 要求只能由 Https 承载)

Service Worker 的注意事项:


  • Service worker 运行在 worker 上下文(self) –> 不能访问 DOM(这里其实和 Web Worker 是一样的);
  • 它设计为完全异步,同步 API(如 XHR 和 localStorage)不能在 service worker 中使用;
  • 出于安全考量,Service workers 只能由 HTTPS 承载;
  • 某些浏览器的用户隐私模式,Service Worker 不可用;
  • 其生命周期与页面无关(关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动)。

Service Worker 缓存优先的示意图:

Service workers 所支持的事件:

通常遵循以下基本步骤来使用 service workers:


  1. service worker URL 通过 serviceWorkerContainer.register() 来获取和注册。
  2. 如果注册成功,service worker 就在 ServiceWorkerGlobalScope 环境中运行; 这是一个特殊类型的 worker 上下文运行环境,与主运行线程(执行脚本)相独立,同时也没有访问 DOM 的能力。
  3. service worker 现在可以处理事件了。
  4. 受 service worker 控制的页面打开后会尝试去安装 service worker。最先发送给 service worker 的事件是安装事件(在这个事件里可以开始进行填充 IndexDB和缓存站点资源)。这个流程同原生 APP 或者 Firefox OS APP 是一样的 — 让所有资源可离线访问。
  5. 当 oninstall 事件的处理程序执行完毕后,可以认为 service worker 安装完成了。
  6. 下一步是激活。当 service worker 安装完成后,会接收到一个激活事件(activate event)。 onactivate 主要用途是清理先前版本的 service worker 脚本中使用的资源。
  7. Service Worker 现在可以控制页面了,但仅是在 register()  成功后的打开的页面。也就是说,页面起始于有没有 service worker ,且在页面的接下来生命周期内维持这个状态。所以,页面不得不重新加载以让 service worker 获得完全的控制。

PWA 实现

一个简单的 PWA demo 很简单,新建项目目录,然后:

touch index.html
touch sw.js
npm install serve -g

之后进行简单的 html 和 sw.js 文件的编写:

/** login.html */



/** sw.js */
const CACHE_NAME = 'cache-v1';self.addEventListener('install', (event => {console.log('---------install-----------', event);// event.waitUntil(self.skipWaiting());event.waitUntil(caches.open(CACHE_NAME).then(cache => {// 资源列表,不要人工获取cache.addAll(['/','./index.css'])}));
}));self.addEventListener('activate', (event => {fetch('./userInfo.json', { method: 'post', body: { a: 1, b: 2 } })console.log('--------activate----------', event);// event.waitUntil(self.clients.claim());event.waitUntil(caches.keys().then(cacheNames => {return Promise.all(cacheNames.map(cacheName => {if (cacheName !== CACHE_NAME) {return cacheNames.delete(cacheName);}}))}))
}));self.addEventListener('fetch', (event => {console.log('--------fetch---------', event);event.respondWith(caches.open(CACHE_NAME).then(cache => {return cache.match(event.request).then(respOnse=> {if (response) {return response;}// https://stackoverflow.com/questions/68522967/failed-to-execute-put-on-cache-request-method-post-is-unsupported-pwa-sif ((event.request.url.indexOf('http') === 0)) {return fetch(event.request).then(respOnse=> {// Check if we received a valid responseif (!response || response.status !== 200 || response.type !== 'basic') {return response;}if (!event.request.url.endsWith('styles.css')) {// IMPORTANT: Clone the response. A response is a stream// and because we want the browser to consume the response// as well as the cache consuming the response, we need// to clone it so we have two streams.console.log('------event.request------', event.request)const respOnseToCache= response.clone();cache.put(event.request, responseToCache);}return response;})}})}))
}))self.addEventListener('push', event => {event.waitUntil(// Process the event and display a notification.self.registration.showNotification("Hey!"));
});self.addEventListener('notificationclick', event => {// Do something with the event event.notification.close();
});self.addEventListener('notificationclose', event => {// Do something with the event
});/** manifest.json */
{"name": "Progressive Web App","short_name": "PWA","description": "Progressive Web App.","icons": [{"src": "/icon.png","sizes": "288x288","type": "image/png"}],"start_url": "/","display": "standalone","theme_color": "#B12A34","background_color": "#B12A34"
}

App Shell 模型 是构建 Progressive Web App 的一种方式,这种应用能可靠且即时地加载到用户屏幕上,与本机应用相似。App“shell”是支持用户界面所需的最小的 HTML、CSS 和 Javascript,如果离线缓存,可确保在用户重复访问时提供即时、可靠的良好性能。这意味着并不是每次用户访问时都要从网络加载 App Shell,只需要从网络中加载必要的内容。对于使用包含大量 Javascript 的架构的单页应用来说,App Shell 是一种常用方法。这种方法依赖渐进式缓存 Shell(使用 Service Worker 线程)让应用运行,接下来,为使用 Javascript 的每个页面加载动态内容。App Shell 非常适合用于在没有网络的情况下将一些初始 HTML 快速加载到屏幕上。

PWA 安装后,就会出现在桌面/Chrome 应用里面:

 支持卸载:

PWA 的优劣势:

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


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

总结


推荐阅读
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 使用ArcGIS for Java和Flex浏览自定义ArcGIS Server 9.3地图
    本文介绍了如何在Flex应用程序中实现浏览自定义ArcGIS Server 9.3发布的地图。这是一个基本的入门示例,适用于初学者。 ... [详细]
  • 本文详细介绍了 InfluxDB、collectd 和 Grafana 的安装与配置流程。首先,按照启动顺序依次安装并配置 InfluxDB、collectd 和 Grafana。InfluxDB 作为时序数据库,用于存储时间序列数据;collectd 负责数据的采集与传输;Grafana 则用于数据的可视化展示。文中提供了 collectd 的官方文档链接,便于用户参考和进一步了解其配置选项。通过本指南,读者可以轻松搭建一个高效的数据监控系统。 ... [详细]
  • 基于iSCSI的SQL Server 2012群集测试(一)SQL群集安装
    一、测试需求介绍与准备公司计划服务器迁移过程计划同时上线SQLServer2012,引入SQLServer2012群集提高高可用性,需要对SQLServ ... [详细]
  • 用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    HTTP协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的HTTP的网站是不 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 本文最初发表在Thorben Janssen的Java EE博客上,每周都会分享最新的Java新闻和动态。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • window下的python安装插件,Go语言社区,Golang程序员人脉社 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 本文介绍了如何在 macOS 上安装 HL-340 USB 转串口驱动,并提供了详细的步骤和注意事项。包括下载驱动、关闭系统完整性保护、安装驱动以及验证安装的方法。 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
author-avatar
销魂苗苗若郗
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有