最近公司里让我研究PWA,经过几天的研究发现PWA竟是如此万能,功能接近手机原生APP,最大的优点是它的离线缓存机制,这主要得益于ServiceWorker!
离线只是它的一种功能表现而已,具体说来,它可以:
让我们的Web App在无网(offline)情况下可以访问,甚至使用部分功能,而不是展示“无网络连接”的错误页;
让我们在弱网的情况下,能使用缓存快速访问我们的应用,提升体验;
在正常的网络情况下,也可以通过各种自发控制的缓存方式来节省部分请求带宽;
那么,Service Worker是什么呢?你可以把Service Worker简单理解为一个独立于前端页面,在后台运行的进程。因此,它不会阻塞浏览器脚本的运行,同时也无法直接访问浏览器相关的API(例如:DOM、localStorage等)。此外,即使在离开你的Web App,甚至是关闭浏览器后,它仍然可以运行。它就像是一个在Web应用背后默默工作的勤劳小蜜蜂,处理着缓存、推送、通知与同步等工作。所以,要学习PWA,绕不开的就是Service Worker。
Service Worker是如何实现离线可用的?
Service Worker是如何让我们在离线的情况下也能访问Web App的。当然,离线访问只是其中一种表现。
首先,我们想一下,当访问一个web网站时,我们实际上做了什么呢?总体上来说,我们通过与与服务器建立连接,获取资源,然后获取到的部分资源还会去请求新的资源(例如html中使用的css、js等)。所以,粗粒度来说,我们访问一个网站,就是在获取/访问这些资源。
可想而知,当处于离线或弱网环境时,我们无法有效访问这些资源,这就是制约我们的关键因素。因此,一个最直观的思路就是:如果我们把这些资源缓存起来,在某些情况下,将网络请求变为本地访问,这样是否能解决这一问题?是的。但这就需要我们有一个本地的cache,可以灵活地将各类资源进行本地存取。
有了本地的cache还不够,我们还需要能够有效地使用缓存、更新缓存与清除缓存,进一步应用各种个性化的缓存策略。而这就需要我们有个能够控制缓存的“worker”——这也就是Service Worker的部分工作之一。顺便多说一句,可能有人还记得 ApplicationCache 这个API。当初它的设计同样也是为了实现Web资源的缓存,然而就是因为不够灵活等各种缺陷,如今已被Service Worker与cache API所取代了。
Service Worker有一个非常重要的特性:你可以在Service Worker中监听所有客户端(Web)发出的请求,然后通过Service Worker来代理,向后端服务发起请求。通过监听用户请求信息,Service Worker可以决定是否使用缓存来作为Web请求的返回。
下图展示普通Web App与添加了Service Worker的Web App在网络请求上的差异:
这里需要强调一下,虽然图中好像将浏览器、SW(Service Worker)与后端服务三者并列放置了,但实际上浏览器(你的Web应用)和SW都是运行在你的本机上的,所以这个场景下的SW类似一个“客户端代理”。
了解了基本概念之后,就可以具体来看下,我们如何应用这个技术来实现一个离线可用的Web应用。
如何使用Service Worker实现离线可用的“秒开”应用
注册Service Worker
注意,我们的应用始终应该是渐进可用的,在不支持Service Worker的环境下,也需要保证其可用性。要实现这点,可以通过特性检测,在index.js中来注册我们的Service Worker(sw.js):
这里我们将sw.js文件注册为一个Service Worker,注意文件的路径不要写错了。
值得一提的是,Service Worker的各类操作都被设计为异步,用以避免一些长时间的阻塞操作。这些API都是以Promise的形式来调用的。所以你会在接下来的各段代码中不断看到Promise的使用。如果你完全不了解Promise,可以先在这里了解基本的Promise概念:Promise(MDN)和JavaScript Promise:简介。
Service Worker的生命周期
当我们注册了Service Worker后,它会经历生命周期的各个阶段,同时会触发相应的事件。整个生命周期包括了:installing --> installed --> activating --> activated --> redundant。当Service Worker安装(installed)完毕后,会触发install事件;而激活(activated)后,则会触发activate事件。
下面的例子监听了install事件:
self
是Service Worker中一个特殊的全局变量,类似于我们最常见的window
对象。self
引用了当前这个Service Worker。
缓存静态资源
通过上一节,我们已经学会了如何添加事件监听,来在合适的时机触发Service Worker的相应操作。现在,要使我们的Web App离线可用,就需要将所需资源缓存下来。我们需要一个资源列表,当Service Worker被激活时,会将该列表内的资源缓存进cache。
可以看到,首先在cacheFiles
中我们列出了所有的静态资源依赖。注意其中的'/'
,由于根路径也可以访问我们的应用,因此不要忘了将其也缓存下来。当Service Worker install时,我们就会通过caches.open()
与cache.addAll()
方法将资源缓存起来。这里我们给缓存起了一个cacheName
,这个值会成为这些缓存的key。
上面这段代码中,caches
是一个全局变量,通过它我们可以操作Cache相关接口。
使用缓存的静态资源
到目前为止,我们仅仅是注册了一个Service Worker,并在其install时缓存了一些静态资源。然而,如果这时运行这个demo你会发现——“图书搜索”这个Web App依然无法离线使用。
为什么呢?因为我们仅仅缓存了这些资源,然而浏览器并不知道需要如何使用它们;换言之,浏览器仍然会通过向服务器发送请求来等待并使用这些资源。那怎么办?
聪明的你应该想起来了,我们在文章前半部分介绍Service Worker时提到了“客户端代理”——用Service Worker来帮我们决定如何使用缓存。
下图是一个简单的策略:
浏览器发起请求,请求各类静态资源(html/js/css/img);
Service Worker拦截浏览器请求,并查询当前cache;
若存在cache则直接返回,结束;
若不存在cache,则通过fetch
方法向服务端发起请求,并返回请求结果给浏览器
fetch
事件会监听所有浏览器的请求。e.respondWith()
方法接受Promise作为参数,通过它让Service Worker向浏览器返回数据。caches.match(e.request)
则可以查看当前的请求是否有一份本地缓存:如果有缓存,则直接向浏览器返回cache
;否则Service Worker会向后端服务发起一个fetch(e.request)
的请求,并将请求结果返回给浏览器。
到目前为止,运行我们的demo:当第一联网打开“图书搜索”Web App后,所依赖的静态资源就会被缓存在本地;以后再访问时,就会使用这些缓存而不发起网络请求。因此,即使在无网情况下,我们似乎依旧能“访问”该应用。
更新静态缓存资源
然而,如果你细心的话,会发现一个小问题:当我们将资源缓存后,除非注销(unregister)sw.js、手动清除缓存,否则新的静态资源将无法缓存。
解决这个问题的一个简单方法就是修改cacheName
。由于浏览器判断sw.js是否更新是通过字节方式,因此修改cacheName
会重新触发install并缓存资源。此外,在activate事件中,我们需要检查cacheName
是否变化,如果变化则表示有了新的缓存资源,原有缓存需要删除。
待续.........
分享到:
相关推荐
Android-PWA-Wrapper 是一个开源项目,其主要目标是帮助开发者将支持离线功能的渐进式Web应用程序(PWA)转化为原生的Android应用程序。这个工具为开发者提供了一个便捷的方式,让他们能够利用已有的PWA,通过简单的...
标题 "PWA-Weather-App-main-源码.rar" 暗示了这是一个关于Progressive Web App(PWA)的天气应用的源代码压缩包。PWA是一种利用现代Web技术构建的应用程序,它旨在提供类似原生应用的用户体验,同时保持网页的便捷...
"PWA-Weather-App-源码.rar" 文件包含了一个实现这一技术的天气应用的完整源代码。通过深入分析这个源码,我们可以学习到如何构建一个功能丰富的PWA,尤其是与天气查询相关的功能。 1. **PWA基础概念** PWA的核心...
`laravel-pwa-manifest`是Laravel 5.5的一个助手工具,专门用于帮助开发者轻松生成PWA的基本清单文件。 PWA的清单文件(manifest.json)是定义应用在Web环境中的关键信息,包括应用名称、图标、启动屏幕显示、主题...
AF2301PWA-VB是一款P沟道MOSFET(金属氧化物半导体场效应晶体管),采用SOT23封装,适用于各种电子应用。这款MOSFET的关键特性在于其低的导通电阻(RDS(on))和高效率设计。以下是关于AF2301PWA-VB的一些详细技术...
webpack-pwa-manifest 寻找愿意帮助的人! webpack-pwa-manifest是一个webpack插件,可为您的渐进式Web应用程序生成一个“ manifest.json”,并具有自动图标大小调整和指纹识别支持。 如果在配置上使用inject ,请...
npx vue-pwa-asset-generator -a {512x512_png_source | svg_source} [-o {output_folder}] 该软件包为您创建在带有PWA插件的VueJS应用中使用的所有默认资产,以及带有icons属性设置的清单JSON。 安装 您可以使用...
零配置,用于安装PWA功能。 为什么很棒 零配置,用于安装PWA功能。 尽管作为快速安装Service Worker支持的轻量级工具非常有用,但它目前并未提供用于安装特定“功能”的...$ npm i pwa-installer 用纱安装 $ yarn add
《PyPI官网下载:molo.pwa-1.0.1-py2-none-any.whl——深入了解Python包管理与PyPI》 在Python的世界里,PyPI(Python Package Index)是开发者们分享和获取开源软件包的主要平台。本文将详细探讨PyPI、Python包的...
标题中的“pwa-note”指的是一个 Progressive Web App (PWA) 项目,它是一个便签应用,旨在提供离线功能,使用户即使在无网络连接的情况下也能使用。这个项目是开发者学习如何构建PWA的一个实践案例。 描述部分揭示...
react-pwa-installer-提示 直接在您的应用程序内提供您自己的自定义安装流程,直接在应用程序的用户界面内提供渐进式Web应用程序(PWA),使用户更容易在其移动或台式设备上安装PWA。 包对 应用内安装流程:尽管...
Angular-angular-pwa-seed.zip,多平台角度项目(web/pwa,移动和桌面)和离子(可选引导)-示例:https://angular-pwa-seed.netlify.comangular pwa seed,Angularjs于2016年发布,是Angularjs的重写版。它专注于良好...
【描述】:这个压缩包“budget-tracker-pwa-源码.rar”包含了一个预算追踪渐进式Web应用程序(Progressive Web App,简称PWA)的源代码。PWA是一种介于传统网页应用和原生移动应用之间的新型应用类型,它能够提供...
**iOS-PWA-Wrapper** 是一个专为iOS平台设计的封装工具,它的主要目标是将一个**Progressive Web App (PWA)** 转变为一个原生的iOS应用。通过这个工具,开发者能够利用Web技术(如HTML、CSS和JavaScript)开发的PWA...
Angular-angular-pwa-course.zip,Angular PWA课程-构建渐进式网络应用Angular PWA课程-构建当今网络的未来,Angularjs于2016年发布,是Angularjs的重写版。它专注于良好的移动开发、模块化和改进的依赖注入。angular...
3. **PWA Builder**:这是一套工具,包括`pwa-buildpack`和`pwa-devserver`,用于构建、打包和部署PWA应用。`pwa-buildpack`处理项目构建,而`pwa-devserver`则提供了一个本地开发环境。 4. **Percy**:这是Magento...
$ npm install vue-pwa-install 用法 作为插件 VuePwaInstallMixin将注入到每个组件中。 import VuePwaInstallPlugin from "vue-pwa-install" ; Vue . use ( VuePwaInstallPlugin ) ; 作为混音 您可以将...
pwa-add-home-ios pwa-add-home-ios 开箱即用,将您的pwa带到iOS并进行陷波检测!安装npm install --save pwa-add-home-ios 或配纱yarn add pwa-add-home-ios用法import React , { Component } from 'react' ;import...
在"next-js-pwa-create-next-app"项目中,开发者利用`create-next-app`创建了一个集成Next.js与PWA功能的应用。这个项目的核心目标是展示如何在Next.js应用中实现PWA特性,提升网页应用的用户体验和性能。 首先,要...