Service Worker

文章目录

      • 简介
      • 主要功能
      • 生命周期
      • 代码演示
        • 使用 Workbox 快速生成 Service Worker
          • 安装 Workbox CLI
          • 初始化 Workbox 配置
          • 生成 Service Worker
          • 注册Service Worker
        • 离线功能
          • 缓存静态资源
          • 拦截请求并返回缓存
          • 测试离线功能

简介

什么是Service Worker?

Service Worker 是一种可编程的网络代理,是现代 Web 应用(PWA)不可或缺的一部分。它独立于网页运行,运行在单独的线程中,因此不会阻塞页面主线程。

主要功能

  • 离线支持:通过拦截fetch事件,可以将网页的静态资源(如
    HTML、CSS、JavaScript、图片等)缓存到本地。当用户再次访问时,即使没有网络连接,也可以从缓存中加载资源,实现离线访问。
  • 推送通知:Service Worker 可以接收来自服务器的推送消息,并在用户没有打开网页的情况下显示通知。
  • 后台同步:即使网页关闭,Service Worker 也可以在后台同步数据。例如,一个笔记应用可以使用 Service Worker
    在后台将用户的笔记同步到服务器。
  • 消息传递:网页和 Service Worker 之间可以通过postMessage
    API进行双向通信。例如,网页可以向 Service Worker 发送请求,Service Worker 处理请求后将结果返回给网页。
  • 拦截请求:Service Worker可以拦截所有来自网页的网络请求,并根据需要修改请求或返回缓存的响应。这可以用于实现各种功能,如广告拦截、自定义缓存策略等。

生命周期

注册(Register):通过navigator.serviceWorker.register()方法注册 Service Worker。如果注册成功,会返回一个ServiceWorkerRegistration对象,否则会抛出错误。
安装(Install):注册成功后,Service Worker进入安装阶段。这个阶段会触发install事件,开发者可以在这个阶段执行初始化操作,如缓存必要的资源。
激活(Activate):安装完成后,Service Worker 进入等待(waiting)状态。当所有旧版本的 Service Worker 控制的页面关闭后,或者通过self.skipWaiting()方法跳过等待阶段,Service Worker进入激活(activating)状态。这个阶段会触发activate事件,通常用于清理旧缓存和旧资源。
控制(Control):激活后,Service Worker 开始控制页面,并可以拦截网络请求。

if ('serviceWorker' in navigator) {
            window.addEventListener('load', function () {
                navigator.serviceWorker.register('/service-worker.js')
                   .then(function (registration) {
                        console.log('Service Worker 注册成功,作用域:', registration.scope);
                    })
                   .catch(function (error) {
                        console.log('Service Worker 注册失败:', error);
                    });
            });
        }

service-worker.js

// 安装阶段
self.addEventListener('install', function (event) {
    console.log('Service Worker 开始安装');
    event.waitUntil(
        caches.open('my - cache - v1')
           .then(function (cache) {
                return cache.addAll([
                    '/',
                    '/index.html'
                ]);
            })
    );
    self.skipWaiting();
});

// 激活阶段
self.addEventListener('activate', function (event) {
    console.log('Service Worker 开始激活');
    event.waitUntil(
        caches.keys().then(function (cacheNames) {
            return Promise.all(
                cacheNames.filter(function (cacheName) {
                    // 过滤掉不需要的缓存
                    return cacheName.startsWith('my - cache -') && cacheName!== 'my - cache - v1';
                }).map(function (cacheName) {
                    return caches.delete(cacheName);
                })
            );
        })
    );
    self.clients.claim();
});

// 拦截请求阶段
self.addEventListener('fetch', function (event) {
    console.log('Service Worker 拦截请求:', event.request.url);
    event.respondWith(
        caches.match(event.request)
           .then(function (response) {
                if (response) {
                    return response;
                }
                return fetch(event.request);
            })
    );
});    

代码演示

使用 Workbox 快速生成 Service Worker

Workbox 是 Google 推出的工具库,可以简化 Service Worker 的开发和配置。

安装 Workbox CLI
npm install workbox-cli --save-dev
初始化 Workbox 配置

在项目根目录下生成 workbox-config.js 文件

npx workbox wizard
module.exports = {
  globDirectory: './',
  globPatterns: ['**/*.{html,js,css,png,svg}'],
  swDest: 'sw.js',
  runtimeCaching: [
    {
      urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
      handler: 'CacheFirst',
      options: {
        cacheName: 'images',
        expiration: {
          maxEntries: 10,
        },
      },
    },
  ],
};
生成 Service Worker

该命令会根据workbox-config.js中的配置生成一个sw.js文件(默认文件名),这就是你的 Service Worker 文件。

npx workbox generateSW workbox-config.js
注册Service Worker

在入口文件js处添加以下代码

  if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
      navigator.serviceWorker.register('/sw.js')
     .then(registration => {
          console.log('Service Worker注册成功', registration.scope);
        })
     .catch(err => {
          console.log('Service Worker注册失败', err);
        });
    });
  }
离线功能
缓存静态资源

修改 Service Worker 文件,缓存 HTML、CSS、JS 和图片等静态资源。

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open('v1').then((cache) => {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles.css',
        '/app.js',
        '/logo.png'
      ]);
    })
  );
});
拦截请求并返回缓存
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});
测试离线功能

打开 Chrome DevTools(F12)。
切换到 Application 选项卡。
在 Service Workers 面板中,勾选 Offline。
刷新页面,检查是否能够正常加载。

你可能感兴趣的:(前端)