如何在 PWA 中使用 Service Worker

Service Worker 是一种 JavaScript 文件,可以拦截并处理 Web 应用程序的网络请求。在 PWA 中使用 Service Worker 可以提高应用程序的性能,减少网络请求,实现离线访问等功能。本文将详细介绍 Service Worker 的原理、如何在 PWA 中使用 Service Worker,以及示例代码。

Service Worker 的原理

Service Worker 是一种独立于网页的 JavaScript 线程,可以在后台运行,拦截并处理网络请求。在 Service Worker 中,可以监听网页发起的网络请求,进行自定义的响应处理。Service Worker 会被保存在用户设备中,在用户首次访问 PWA 时,会被下载和安装。

在 PWA 中使用 Service Worker

要在 PWA 中使用 Service Worker,需要完成以下几个步骤:

1. 注册 Service Worker

在 PWA 的 HTML 文件中,通过 JavaScript 注册 Service Worker,代码如下:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('Service Worker 注册成功!')
    })
    .catch(err => {
      console.log('Service Worker 注册失败:', err)
    })
}

2. 编写 Service Worker

创建一个名为 sw.js 的文件,在其中编写 Service Worker 的逻辑。通常情况下,Service Worker 主要包含以下两个事件监听:

  • install 事件:当 Service Worker 安装成功之后触发,一般在该事件中完成缓存的操作。
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('pwa-cache-v1')
      .then(cache => {
        return cache.addAll([
          '/',
          '/index.html',
          '/css/styles.css',
          '/js/app.js'
        ])
      })
  )
})
  • fetch 事件:当网页发起网络请求时触发,可以在该事件中进行自定义响应处理。
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response
        }
        return fetch(event.request)
      })
  )
})

3. 添加离线访问支持

在 Service Worker 的 install 事件中,可以将需要缓存的文件添加到缓存中。当用户打开 PWA 时,缓存文件可以直接从本地加载,从而实现离线访问功能。

4. 更新 Service Worker

当 Service Worker 的代码发生变化,需要更新 Service Worker。Service Worker 更新分为两个步骤:首先在 sw.js 文件中增加代码版本号,然后通过 self.skipWaiting() 方法强制 Service Worker 立即激活。

const CACHE_VERSION = 'pwa-cache-v2'

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_VERSION)
      .then(cache => {
        return cache.addAll([
          '/',
          '/index.html',
          '/css/styles.css',
          '/js/app.js'
        ])
      })
  )
})

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.filter(cacheName => {
          return cacheName !== CACHE_VERSION
        }).map(cacheName => {
          return caches.delete(cacheName)
        })
      )
    })
  )
  self.clients.claim()
})

示例代码

完整的 PWA 示例代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>PWA 示例</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="manifest" href="/manifest.json">
    <link rel="stylesheet" href="/css/styles.css">
  </head>
  <body>
    <h1>Hello, PWA!</h1>
    <script src="/js/app.js"></script>
  </body>
</html>
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('Service Worker 注册成功!')
    })
    .catch(err => {
      console.log('Service Worker 注册失败:', err)
    })
}

const CACHE_VERSION = 'pwa-cache-v1'

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_VERSION)
      .then(cache => {
        return cache.addAll([
          '/',
          '/index.html',
          '/css/styles.css',
          '/js/app.js'
        ])
      })
  )
})

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.filter(cacheName => {
          return cacheName !== CACHE_VERSION
        }).map(cacheName => {
          return caches.delete(cacheName)
        })
      )
    })
  )
  self.clients.claim()
})

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

总结

在 PWA 中使用 Service Worker 可以提高应用程序的性能,减少网络请求,实现离线访问等功能。本文介绍了 Service Worker 的原理、如何在 PWA 中使用 Service Worker,以及示例代码。希望本文对前端开发者能够有一定的指导意义。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/659f917dadd4f0e0ff823328


纠错反馈