构建脱机工作的应用程序

null

长期以来,离线功能,后台同步和推送通知使本机应用与其网络对应产品区别开来。该Service Worker API是一种改变游戏规则的技术,使公平竞争。在本教程中,我们将使用它来构建一个即使在没有互联网连接的情况下也可以提供内容的页面。

01. HTTPS服务器

考虑Service Workers的最简单方法是作为一段代码,由客户端计算机上的站点安装,在后台运行,然后使发送到该站点的请求被拦截和操纵。因为这是一个强大的功能,要在实时环境中与Service Workers一起工作,您需要通过HTTPS运行。通过确保浏览器从页面接收的服务工作者是真实的,这可以确保它们无法被利用。

但是,出于开发目的,我们可以在没有HTTPS的情况下运行HTTP://本地主机/被允许作为此规则的例外。最简单的入门方法是使用npmHTTP服务器包。

npm install http-server -g http-server -p 8000 -c-1

02.设置基本页面

现在服务器上没有任何内容,所以让我们创建一个基本页面来提供服务。我们将创建一个新的index.html文件,当我们运行服务器时,现在可以访问它HTTP://本地主机:8000

在此阶段,您会发现如果您终止HTTP服务器并在浏览器中刷新页面,您将收到一个错误页面,因为无法访问该站点。这完全是预期的,因为我们还没有缓存任何离线内容。

服务人员

欢迎

内容在这里

03.注册服务工作者

我们现在已经运行了一个相当不起眼的页面,现在是时候开始考虑实现服务工作者了。在我们编写代码之前,值得花一点时间来了解服务工作者的生命周期。

这个过程随着JavaScript中的服务工作者的“注册”开始,告诉浏览器开始安装工作者 - 这是其生命周期的第一步。在整个生命周期中,服务工作者将处于以下状态之一:

  • 安装:一旦注册了Service Worker,其安装通常用于下载和缓存静态内容
  • 安装:该工人理论上已准备好使用,但不会立即激活
  • 激活:如果没有现有的服务工作者,或者某些条件导致现有服务工作者过期,则已安装的服务工作者将自行激活;激活通常用于从缓存的脱机内容中清除旧文件
  • 活性:服务工作者现在可以控制文档,并可以处理请求
  • 冗余:如果Service Worker未能安装或激活,或者由较新的Service Worker替换

04.检查你是否已注册

我们注册一名服务工作者。这有效地将浏览器指向定义Service Worker行为的JavaScript文件。使用serviceWorker对象完成注册,该对象是API的入口点。在尝试这样做之前,我们还会检查浏览器中是否存在API。

寄存器()每次加载页面时都可以安全地调用函数,浏览器将确定服务工作者是否已经注册。

if(导航器中的'serviceWorker'){window.addEventListener('load',function(){navigator.serviceWorker.register('serviceworker.js',{scope:'。/'}} .then(functional(registration){ console.log(“服务工作者注册成功。”);},函数(错误){console.log(“错误注册服务工作者:”+错误);});}); }

05.实施服务工作者

接下来,我们需要实现Service Worker本身。服务工作者可以在页面上监听与其自身生命周期和活动相关的一系列事件。最重要的是安装,激活和获取。

让我们从创建一个监听器开始安装Event,一旦工人的安装完成就会触发。这使我们能够指示服务工作者将当前文件夹中的一些脱机内容添加到缓存中。我们还需要命名我们的缓存 - 因为旧的缓存可以持久化,更新/版本化此缓存名称使您可以在以后提供更新版本的内容。

var currentCache ='demo-cache'; self.addEventListener('install',event => {event.waitUntil(caches.open(currentCache).then(function(cache){console.log(“将内容添加到缓存中。”);返回cache.addAll([' ./index_offline.html','。/ kitty_offline.jpg','。/ custom.css']);}));});

06.获取事件

我们的页面现在将在加载时缓存内容,但我们需要一些机制来拦截请求并将它们重定向到此缓存。要做到这一点,我们需要倾听事件,在获取我们的请求时触发的index.html文件是通过网络制作的。然后,我们将请求与缓存进行匹配,并在找到时提供缓存的资源。否则,我们将回退到服务器的Fetch API请求。

在这一点上值得注意的是,我们非常依赖JavaScript Promises来工作。这些可能有点棘手,如果您之前没有使用它们,那么值得熟悉。

self.addEventListener('fetch',event => {event.respondWith(caches.match(event.request).then(response => {return response || fetch(event.request);}));});

07.扩展获取事件

如果您现在测试它(终止HTTP服务器并刷新页面),您会发现您的页面在线和离线都有效。但是,您可能需要更智能的脱机行为,在服务器不可用时可以使用不同的内容或功能。

为实现这一目标,我们可以扩展我们的事件响应进一步特定地检查导航请求,并在检测到一个时响应不同的离线页面。这个Index_offline.html文件可以是您的在线页面的变体,或完全不同的东西,也可以使用您已缓存的其他资源,例如Custom.css

self.addEventListener('fetch',event => {if(event.request.mode ==='navigate'){event.respondWith(fetch(event.request).catch(error => {console.log(“Page返回离线内容。“);返回caches.match('。/ index_offline.html');}));} else {event.respondWith(caches.match(event.request).then(response => {return响应|| fetch(event.request);}));}});

08.删除缓存

我们需要还有一件事。如果您现在尝试修改离线内容,您会发现在测试页面时它不会更新 - 您仍然可以使用旧版本!这是因为旧文件仍然被缓存。

您需要实现一些东西来清除缓存中过时的文件,以防止它们被提供。这是通过回应一个来完成的启用Event并删除与currentCache中指定的名称不匹配的所有缓存。然后,您可以在每次修改脱机内容时向currentCache添加版本号,以确保刷新。

this.addEventListener('activate',event => {var activeCaches = [currentCache]; console.log(“Service worker activated。检查缓存是最新的。”); event.waitUntil(caches.keys()。然后(keyList => {return Promise.all(keyList.map(key => {if(activeCaches.indexOf(key)=== -1){console.log(“删除旧缓存”+键);返回缓存。 delete(key);}}));}));});

本文发表于Web Designer杂志第268期。现在订阅。

阅读更多:



翻译字数超限