您的位置:

ServiceWorker是什么?

ServiceWorker 是 PWA 技术栈中的一个重要成员,它是一个用于使Web 应用在离线状态下依然可以工作,且具有网络拦截的浏览器功能。这个功能由一段运行在浏览器后台线程的 JavaScript 代码来实现。

一、ServiceWorker的作用

ServiceWorker 的主要功能是使得 Web 应用程序可以离线运行。通过 ServiceWorker 可以缓存 Web 应用在用户设备上的一些文件,如HTML、JS、CSS、图片等,这样即使用户离线,也能通过ServiceWorker的缓存功能加载并渲染对应的 Web 应用页面。

另外,ServiceWorker 还能够通过网络拦截功能对接口的请求做一些处理,这可以用于 Offline First 等场景的开发。例如当Web 应用在用户设备上没有网络或者网络差的情况下,ServiceWorker 可以使用它的缓存功能提供一些基础信息或者降级处理。当然,ServiceWorker 的功能不止这些,还可以配合 Push Notification 等技术进行 Web 应用的推送、更新等操作。

二、ServiceWorker无效的原因

ServiceWorker 运行的环境比较独特,它没有 window 或 document 的对象,也没有 localStorage 或者 indexedDB 之类的浏览器 API。这样导致ServiceWorker中某些操作是不能进行的。

另外,由于 ServiceWorker 运行在后台线程之中,所以为了确保不会出现异常情况,ServiceWorker 只能响应HTTPS或者本地环境,这也是 ServiceWorker 无法应用到经典的 HTTP 协议中的一个原因。

三、阮一峰关于ServiceWorker的看法

阮一峰在他的博客中提到过 ServiceWorker:“ServiceWorker 与 Web Worker 非常相似,都是运行在浏览器后台的 JavaScript 线程。ServiceWorker 和传统浏览器 js 不同,它可以脱离标签页运行,具有比较高的独立性,因此可以进行一些操作,比如缓存、推送等。”

在他的看来,ServiceWorker是一种比较快捷、简便的技术,可以极大地提升Web应用的易用性和性能体验。

四、ServiceWorker拦截请求

ServiceWorker 提供了一个对请求的拦截功能,在 ServiceWorker 中可以通过拦截特定类型的请求,例如接口请求或者资源请求,从而完成一些特殊的处理。

self.addEventListener('fetch', (event) => {
  if (event.request.url.includes('your-api-url.com')) {
    event.respondWith(fetch(event.request).then((res) => {
      return res.json().then((data) => {
        return new Response(JSON.stringify(data));
      });
    }));
  }
});

上述代码中,我们监听了 fetch 事件,如果检测到该请求地址包含是某个API地址,则会使用 ServiceWorker 拦截该请求,然后获取响应结果进行数据相关处理后返回。

五、ServiceWorkers是什么意思

ServiceWorkers是指一类服务工作线程。ServiceWorker 是一种比较新的 HTML5 技术,它们被设计成运行在浏览器后台线程。

ServiceWorker 不会和浏览器标签页之间产生显著的交互,这使得它们可以被用于离线应用程序、消息推送、后台数据同步和其他类似的任务。ServiceWorker 的 API 本质上就是 Web Worker API 的一种,但提供了更多的能力和一些不同的限制。

六、ServiceWorker和Web Worker

ServiceWorker 和 Web Worker 非常相似,它们都是后台线程,都不能访问 DOM,提供了新的 JavaScript Worker 类,是 HTML5 中新添加的一种运行在浏览器后台的线程。

在 ServiceWorker 和 Web Worker 中,JavaScript 代码是一个独立的线程,不会阻塞主线程,允许同时做多件事情。

七、苹果ServiceWorker

苹果公司已经支持ServiceWorker技术,苹果 Safari 浏览器在 2017 年 6 月份开始支持ServiceWorker 的注册和使用,这对 PWA 应用的普及有着极为重要的意义。

八、Service workers与负责可靠实时交付的网络应用程序

ServiceWorker 可以让慢速和不可靠的网络情况下的 Web 应用程序依然能够拥有较好的用户体验。通过 ServiceWorker 的事件监听功能,开发者可以在网络离线的情况下,选择香港或者本地缓存提供用户一些基础信息,避免 Web 应用程序传输许多陈旧和冗余的数据。

此外,Service Worker 还为开发者提供了对本地缓存的实时控制功能,可以根据具体情况灵活调整缓存策略,可以选择在页面初始化或者在网络上下文变化之后更新缓存。

九、Service Worker在浏览器的支持情况

目前支持ServiceWorker 的主流浏览器有:

  • Chrome 45+
  • Firefox 44+
  • Opera 32+
  • Edge 17+
  • Safari 11.1+
    Safari 目前仅支持 HTTPS 环境下的 ServiceWorker。

十、Service Workers的完整示例代码

const CACHE_NAME = 'my-site-cache-v1';
const URLS_TO_CACHE = [
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png',
'/pages/offline.html'
];

self.addEventListener('install', (event) => {
 event.waitUntil(
   caches.open(CACHE_NAME)
     .then((cache) => {
       return cache.addAll(URLS_TO_CACHE);
     })
 );
});

self.addEventListener('fetch', (event) => {
 event.respondWith(
   caches.match(event.request)
     .then((response) => {
       if (response) {
         return response;
       }
       return fetch(event.request);
     })
     .catch(() => {
       return caches.match('/pages/offline.html');
     })
 );
});

self.addEventListener('activate', (event) => {
 const cacheWhitelist = ['my-site-cache-v2'];
 event.waitUntil(
   caches.keys()
     .then((cacheNames) => {
       return Promise.all(
         cacheNames.map((cacheName) => {
           if (cacheWhitelist.indexOf(cacheName) === -1) {
             return caches.delete(cacheName);
           }
         })
       );
     })
     .then(() => {
       return self.clients.claim();
     })
 );
});

上述代码就是一个 ServiceWorker 实现离线缓存的完整代码示例。它安装和激活之后就会缓存指定的内容,后面在网络不可达的情况下,会从缓存中读取相应资源。如果缓存不存在,会返回缺省的 offline.html 页面。