Service Worker 实现离线应用思路

1 背景

本地运行一个vue项目,界面如下:
Service Worker 实现离线应用思路_第1张图片
使用 Service Worker 对其进行缓存,预期在停止运行项目时(模拟离线场景)也能够正常访问项目

2 缓存的资源分析

检查 network,浏览器访问:http://localhost:5173/ 时,获取的资源需要包含如下,才能正常展示界面:

  • HTML 文件
  • JS 文件
  • CSS 文件

3 index.html 内容

doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite Apptitle>
  head>
  <body>
    <div id="app">div>
    <div
      style="
        background-color: #fff;
        border-radius: 10px;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        width: 300px;
        padding: 20px;
        text-align: center;
        transition: transform 0.3s ease;
      "
    >
      <img
        src="https://via.placeholder.com/280x150"
        alt="Card Image"
        style="width: 100%; border-radius: 8px; height: auto"
      />
      <h2 style="margin: 20px 0; font-size: 1.5rem">Card Titleh2>
      <p style="font-size: 1rem; color: #555; margin-bottom: 20px">
        This is a simple card with an image, title, and description. It uses inline styles.
      p>
      <button
        style="
          background-color: #007bff;
          color: white;
          border: none;
          padding: 10px 20px;
          font-size: 1rem;
          border-radius: 5px;
        "
      >
        Click Me
      button>
    div>
    <script type="module" src="/src/main.ts">script>
  body>
html>

4 注册/删除 Service Worker

在 index.html 中注册Service Worker

      // 注册 Service Worker 检查浏览器是否支持 Service Worker
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
          navigator.serviceWorker
            .register('/service-worker.js') // 注册 Service Worker
            .then((registration) => {
              console.log('Service Worker 注册成功:', registration)
            })
            .catch((error) => {
              console.log('Service Worker 注册失败:', error)
            })
        })
      }
      // 删除 Service Worker
      if ('serviceWorker' in navigator) {
        // 获取当前注册的 Service Worker
        navigator.serviceWorker.getRegistration().then((registration) => {
          if (registration) {
            // 注销 Service Worker
            registration.unregister().then((boolean) => {
              if (boolean) {
                console.log('Service Worker 已成功注销')
              } else {
                console.log('Service Worker 注销失败')
              }
            })
          } else {
            console.log('没有找到已注册的 Service Worker')
          }
        })
      }

5 service-worker.js 文件

const CACHE_NAME = 'my-app-cache-v1' // 缓存的名称
const URLS_TO_CACHE = [
  '/', // HTML 根页面
  '/src/main.ts', // JS 文件   由于是本地模拟,所以是 /src/
  '/src/assets/main.css' // CSS 文件    由于是本地模拟,所以是 /src/
]

// 安装 Service Worker 时,缓存指定的资源
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('缓存文件...')
      return cache.addAll(URLS_TO_CACHE)
    })
  )
})

// 拦截请求并返回缓存数据(如果有)
self.addEventListener('fetch', (event) => {
  console.log('event.request.url ', event.request.url)
  event.respondWith(
    caches.match(event.request, { ignoreSearch: true }).then((cachedResponse) => { // 设置 ignoreSearch: true 来忽略查询参数,例如,/index.html 和 /index.html?version=1 将被视为相同。
      // 如果缓存中有匹配的响应,则返回缓存
      if (cachedResponse) {
        console.log('从缓存中提供:', event.request.url)
        return cachedResponse
      }
      console.log('从网络中提供:', event.request.url)
      // 如果缓存中没有,发送网络请求
      return fetch(event.request)
    })
  )
})

当 Service Worker 安装时,它会缓存资源(如 html、css、.js 等)
缓存的资源包含:

const URLS_TO_CACHE = [
  '/', // HTML 根页面
  '/src/main.ts', // JS 文件   由于是本地模拟,所以是 /src/
  '/src/assets/main.css' // CSS 文件    由于是本地模拟,所以是 /src/
]

当缓存这些资源后,后续请求url如果匹配到了就可以返回,如:

  • ‘http://localhost:5173/src/’ 会匹配到 ‘/’
  • ‘http://localhost:5173/src/main.ts/’ 会匹配到 ‘/src/main.ts’

缓存的资源在cache中可以查看
Service Worker 实现离线应用思路_第2张图片

离线

停止运行项目,模拟离线场景,输入 http://localhost:5173/ 进入项目,可以看到项目正常展示
Service Worker 实现离线应用思路_第3张图片
网络请求中可以看到, html js css 都是通过 serviceworker 返回的缓存
Service Worker 实现离线应用思路_第4张图片

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