热门标签 | 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 实现消息推送,使用浏览器推送功能,吸引用户
  • 渐进式开发,尽管一些浏览器暂时不支持,可以利用上述技术给使用支持浏览器的用户带来更好的体验

总结


推荐阅读
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • uniapp开发H5解决跨域问题的两种代理方法
    本文介绍了uniapp开发H5解决跨域问题的两种代理方法,分别是在manifest.json文件和vue.config.js文件中设置代理。通过设置代理根域名和配置路径别名,可以实现H5页面的跨域访问。同时还介绍了如何开启内网穿透,让外网的人可以访问到本地调试的H5页面。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
  • {moduleinfo:{card_count:[{count_phone:1,count:1}],search_count:[{count_phone:4 ... [详细]
  • {moduleinfo:{card_count:[{count_phone:1,count:1}],search_count:[{count_phone:4 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
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社区 版权所有