当前位置: 首页 > Web前端 > HTML5

【翻译】服务工作者:PWA背后的英雄

时间:2023-04-05 20:00:08 HTML5

原文地址:https://medium.freecodecamp.org/service-workers-the-little-heroes-behind-progressive-web-apps-431cc22d0f16作者:FlavioCopes摘要:本文简要介绍了ServiceWorker作为PWA的核心技术,是如何实现资源缓存和消息推送等功能的,同时也帮助读者理解ServiceWorker的生命周期。ServiceWorker是ProgressiveWebApps的核心。它们帮助我们实现了资源缓存和消息推送两大特性,这些特性原本只有在原生应用中才有。ServiceWorker是您的网页和网络之间的代理,它可以拦截和缓存传入和传出的网络请求。这可以帮助您的应用打造适合离线使用的用户体验。首先介绍一下webworker的概念。它是与指定网页关联的JS文件,在特定的上下文中独立于主线程运行,这样就不会为了数据的计算而牺牲UI的性能,从而避免阻塞。serviceworker是一种特殊的webworker。而正是因为它是子线程,它不能操作DOM。也无法访问LocalStorageAPI和XHRAPI。它只能通过ChannelMessagingAPI与主线程通信。ServiceWorker可以使用以下API:PromisesFetchAPICacheAPI它们只会在HTTPS协议下的网页中工作。(不过本地网络请求不包括在内,因为它们不需要维护安全连接,这也方便我们调试。)当这些应用程序处于非活动状态时使用。接收消息。让我给你几个场景:应用程序在后台运行不活跃;该应用程序已关闭;呈现您网页的浏览器已关闭;那么serviceworker将继续不受影响地工作。ServiceWorker的用处在于可以作为缓冲层处理网络请求和缓存离线需要的资源;它们可用于推送消息。服务人员仅在需要时运行,否则他们将停止工作。支持离线对于传统的网页,离线情况下的用户体验是非常糟糕的。如果用户没有连接到互联网,移动网络应用程序通常会直接停止工作。相对于原生应用,会向用户展示一些友好的提示。这是Chrome中离线页面的图片,显然不是友情提示:也许唯一的好处是点击恐龙就可以免费玩游戏,但我敢肯定你很快就会不耐烦了。不久前,HTML5标准下的AppCache允许Web应用缓存离线资源,但其缺乏灵活性和一些令人困惑的行为也意味着它无法胜任支持离线的任务。现在,serviceworkers是离线缓存的新标准。那么,它实现了什么缓存呢?安装时预缓存的图片、CSS文件、JS文件,在应用的使用过程中会被重复使用。这些资源可以在应用程序第一次打开时被缓存。这也是所谓的AppShell架构的基础。缓存网络请求我们可以使用FetchAPI编辑服务器返回的响应报文,根据服务器是否可达决定是否改用缓存中的响应报文。生命周期一个serviceworker在启动前要经过三个步骤:注册(Registration)安装(Installation)激活(Activation)注册注册阶段是通知浏览器serviceworker的存在,并在后台启动安装。下面是在worker.js中注册一个serviceworker的代码:).then((registration)=>{console.log('ServiceWorker注册完成,范围:',registration.scope)},(err)=>{console.log('ServiceWorker注册失败',err)})})}else{console.log('ServiceWorkersnotsupported')}不管这段代码被调用多少次,如果之前没有注册过serviceworker或者需要更新,浏览器只会进入注册阶段.Scoperegister函数需要一个范围参数来指示服务工作者管理的Web应用程序文件的路径。该参数的默认值为serviceworker文件父目录下的所有文件和所有子文件夹。所以如果你把serviceworker文件放在根目录下,它将管理整个web应用程序。而如果在子文件夹中,则只会管理该路径可以访问的网页。以下示例通过将范围参数指定为/notifications/目录来注册服务工作者。navigator.serviceWorker.register('/worker.js',{scope:'/notifications/'})末尾的/对于防止/notification页面触发serviceworker非常重要。而如果这样写:{scope:'/notifications'},那么serviceworker也会对/notification页面进行操作。注意:serviceworker无法控制其目录之外的文件。即如果serviceworker文件放在/notification文件夹下,则无法控制根目录/或其他不属于/notification的文件。安装如果浏览器发现一个serviceworker已经过期或者之前没有注册过,它就会安装这个serviceworker。self.addEventListener('install',(event)=>{//...});这是使用serviceworker初始化缓存,然后使用CacheAPI缓存APPshell和静态资源的好时机。激活一旦serviceworker注册并安装成功,我们就进入了第三阶段:激活。此时,ServiceWorker可以在加载新页面时开始工作。它在激活前已加载的页面上不起作用,因此只有两种方法可以使其起作用:重新启动应用程序或刷新加载的页面。self.addEventListener('activate',(event)=>{//...});侦听此事件可用于清除旧缓存或删除新版本ServiceWorker不需要的旧资源。更新你需要更新serviceworker来改变文件的一个字节。当再次执行注册代码时,它将被更新。更新后的ServiceWorker仅在所有页面关闭后才开始替换之前的ServiceWorker。仅仅刷新页面是行不通的,因为之前的serviceworker还在运行,并没有被删除。此机制可确保更新不会使之前运行的应用程序或网页崩溃。Fetch事件Fetch事件在浏览器发送网络请求时被触发。这允许我们在发送请求时检查所需的资源是否已存储在缓存中。例如,以下代码使用缓存API来检查请求的URL是否已被缓存。如果是,则返回缓存中的响应数据,否则发送请求并返回响应数据。self.addEventListener('fetch',(event)=>{event.respondWith(caches.match(event.request).then((response)=>{if(response){//entryfoundincachereturnresponse}returnfetch(event.request)}))})BackgroundSync当用户在离线状态下发送网络请求时,BackgroundSyncAPI会延迟请求直到用户离开离线状态。这保证了用户在离线状态下仍然可以使用和操作应用程序。这些离线操作会被存储在队列中,以便在连接到网络后向服务器发送响应请求。(这比显示无限加载图标更好吗?)navigator.serviceWorker.ready.then((swRegistration)=>{//注册一个事件event1returnswRegistration.sync.register('event1')});下面的代码在serviceworker中监听这个事件:self.addEventListener('sync',(event)=>{if(event.tag=='event1'){event.waitUntil(doSomething())}})doSomething()返回一个承诺。如果返回的承诺被拒绝,另一个同步事件将自动开始重试操作,直到返回具有成功状态的承诺。这也使应用程序能够在连接到Internet时立即更新服务器发送的数据。消息推送ServiceWorker使Web应用程序能够像本地用户一样向用户推送消息。其实推送和消息通知是两个不同的概念,它们结合起来的技术就是我们熟悉的消息推送。推送机制使服务器能够将信息发送给serviceworker,然后serviceworker将信息作为通知显示给用户。由于ServiceWorker可以在应用关闭后继续运行,因此它们可以始终监听推送事件。然后他们可以发送通知,或更新应用程序的状态。push事件会在后端通过浏览器推送服务后启动,比如Firebase的push服务。下面的代码演示了webworker如何监听推送事件:给你的消息!',body:'这是消息的正文',icon:'/img/icon-192x192.png',tag:'tag-for-this-notification',}event.waitUntil(self.registration.showNotification(title,options))})关于console.log如果你的代码中包含console.log或者其他类似的控制台输出语句,一定要开启Chrome开发工具中的Preservelog功能。否则,您将看不到任何日志输出,因为serviceworker在页面加载之前就开始执行,此时控制台将被清空。作者总结感谢您阅读本教程,事实上,PWA仍有很多需要学习的地方。如果您有任何见解,请在下面发表评论。译者注:主流浏览器开始逐步支持ServiceWorkers。未来PWA真的会和原生一样吗?未来呢,我觉得现在多了解一点PWA也不是什么坏事。项目地址:https://github.com/WhiteYin/translation