跳转到内容

JavaScript Service Worker

来自代码酷


Service WorkerJavaScript 中一种特殊的 Web Worker,它充当浏览器和网络之间的代理服务器,允许开发者控制网页的缓存行为、拦截网络请求,并实现离线功能。它是 Progressive Web Apps(PWA)的核心技术之一,能够显著提升 Web 应用的性能和用户体验。

概述[编辑 | 编辑源代码]

Service Worker 运行在独立的线程中,与主 JavaScript 线程分离,因此不会阻塞页面渲染。它主要用于:

  • 离线缓存:缓存资源(如 HTML、CSS、JS、图片等),使应用在无网络时仍可运行。
  • 后台同步:在网络恢复后执行延迟的任务。
  • 推送通知:接收服务器推送的消息并显示通知。

Service Worker 基于事件驱动,生命周期包括注册、安装、激活和运行阶段。

生命周期[编辑 | 编辑源代码]

Service Worker 的生命周期包括以下几个关键阶段: 1. 注册:通过 JavaScript 在主线程中注册 Service Worker。 2. 安装:首次注册时触发,通常用于缓存资源。 3. 激活:安装完成后触发,用于清理旧缓存。 4. 运行:处理 fetch、push、sync 等事件。

graph TD A[注册 Service Worker] --> B[安装] B --> C[激活] C --> D[运行]

注册 Service Worker[编辑 | 编辑源代码]

要使用 Service Worker,首先需要在主线程中注册它。以下是一个基本示例:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js')
        .then(registration => {
            console.log('Service Worker 注册成功:', registration.scope);
        })
        .catch(error => {
            console.log('Service Worker 注册失败:', error);
        });
}
  • 输入:`sw.js` 是 Service Worker 脚本文件。
  • 输出:控制台打印注册成功或失败信息。

安装与缓存资源[编辑 | 编辑源代码]

在 `sw.js` 文件中,可以监听 `install` 事件来缓存资源:

const CACHE_NAME = 'my-cache-v1';
const urlsToCache = [
    '/',
    '/styles/main.css',
    '/scripts/main.js',
    '/images/logo.png'
];

self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                return cache.addAll(urlsToCache);
            })
    );
});
  • 解释
 * `CACHE_NAME` 是缓存的唯一标识符。
 * `urlsToCache` 是需要缓存的资源列表。
 * `event.waitUntil` 确保 Service Worker 在缓存完成前不会进入下一阶段。

拦截网络请求[编辑 | 编辑源代码]

Service Worker 可以拦截 fetch 请求,并从缓存中返回响应:

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                // 如果缓存中有资源,则返回缓存
                if (response) {
                    return response;
                }
                // 否则从网络获取
                return fetch(event.request);
            })
    );
});
  • 解释
 * `event.respondWith` 用于提供自定义响应。
 * `caches.match` 检查请求是否在缓存中。

更新 Service Worker[编辑 | 编辑源代码]

当 `sw.js` 文件内容发生变化时,浏览器会检测到并触发更新流程:

self.addEventListener('activate', event => {
    const cacheWhitelist = ['my-cache-v2']; // 新缓存名称
    event.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cacheName => {
                    if (!cacheWhitelist.includes(cacheName)) {
                        return caches.delete(cacheName); // 删除旧缓存
                    }
                })
            );
        })
    );
});
  • 解释
 * `activate` 事件在 Service Worker 激活时触发。
 * `caches.delete` 删除不再需要的旧缓存。

实际应用案例[编辑 | 编辑源代码]

离线应用[编辑 | 编辑源代码]

Service Worker 可用于构建离线可用的 Web 应用,如文档编辑器或阅读器。用户即使在没有网络的情况下,仍然可以访问已缓存的内容。

推送通知[编辑 | 编辑源代码]

结合 Push API,Service Worker 可以接收服务器推送的消息并显示通知:

self.addEventListener('push', event => {
    const options = {
        body: event.data.text(),
        icon: '/images/icon.png',
    };
    event.waitUntil(
        self.registration.showNotification('新消息', options)
    );
});
  • 解释
 * `push` 事件在收到推送消息时触发。
 * `showNotification` 显示浏览器通知。

注意事项[编辑 | 编辑源代码]

  • HTTPS 要求:Service Worker 仅在 HTTPS 或 `localhost` 环境下工作。
  • 作用域限制:Service Worker 只能控制其所在目录及子目录的页面。
  • 缓存策略:需合理设计缓存策略,避免存储过多无用数据。

总结[编辑 | 编辑源代码]

Service Worker 是提升 Web 应用性能和离线能力的关键技术。通过缓存资源、拦截请求和接收推送,开发者可以构建更强大、更可靠的 Web 应用。初学者可以从简单的缓存策略开始,逐步探索更高级的功能,如后台同步和推送通知。

参见[编辑 | 编辑源代码]