什么是 Service Worker?
Service Worker 是在浏览器后台运行的一种脚本,通过它可以拦截和处理网络请求,实现离线缓存、消息推送等功能。
为什么需要 Service Worker?
随着 Web 应用的复杂性不断增加,用户对性能和用户体验的要求也越来越高。Service Worker 可以提高 Web 应用的性能和用户体验,例如:
- 离线缓存:可以让 Web 应用即使在离线状态下也能正常访问。
- 渐进增强:可以根据用户的网络状态提供不同程度的服务。
- 减少网络请求:可以通过缓存和消息推送减少网络请求,提高 Web 应用的性能。
如何在 Angular SPA 应用中使用 Service Worker?
要在 Angular SPA 应用中使用 Service Worker,首先需要使用 @angular/service-worker 模块进行配置。
- 安装 @angular/service-worker 模块:
npm install @angular/service-worker --save
- 在 app.module.ts 中导入 ServiceWorkerModule:
// javascriptcn.com 代码示例 import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; @NgModule({ ... imports: [ BrowserModule, ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }) ], ... }) export class AppModule { }
- 创建一个 Service Worker:
在项目根目录下创建一个 sw.js 文件,用于配置 Service Worker。
// javascriptcn.com 代码示例 importScripts('./ngsw-worker.js'); self.addEventListener('install', event => { console.log('[Service Worker] Installing Service Worker ...'); event.waitUntil( caches.open('static') .then(cache => { console.log('[Service Worker] Precaching App Shell'); cache.addAll([ '/', '/index.html', '/favicon.ico', '/manifest.webmanifest', '/styles.css', '/main.js' ]); }) ); }); self.addEventListener('activate', event => { console.log('[Service Worker] Activating Service Worker ...'); }); self.addEventListener('fetch', event => { console.log('[Service Worker] Fetching something ...'); event.respondWith( caches.match(event.request) .then(response => { if (response) { return response; } return fetch(event.request); }) ); });
代码解释:
- 使用 importScripts 导入 @angular/service-worker 生成的 ngsw-worker.js;
- 在 install 事件中,打开一个缓存(使用 caches.open 方法),并将应用的静态资源添加到缓存中;
- 在 fetch 事件中,先查看缓存中是否有对应的请求,如果有就直接使用缓存中的内容,否则就从网络中动态获取内容。
- 发布应用并打开 Service Worker:
使用以下命令构建和发布应用,在本地启动一个 Web 服务器:
ng build --prod npx http-server dist/my-app
在浏览器中打开本地 Web 服务器中的应用,此时 Service Worker 将被自动安装、激活。
如何测试离线缓存?
- 离线模式:
在浏览器开发者工具中,勾选 Network 标签页中的 Offline 选项,模拟离线状态。
- 缓存清除:
打开浏览器开发者工具中的 Application 标签页,选择 Cache 中的 Cache storage,右击选择 Delete,清除缓存。
如何更新 Service Worker?
当我们更新了 Service Worker,需要提醒用户刷新页面以加载新的代码。而 @angular/service-worker 模块已经为我们提供了更新机制,只需要更新 sw.js 文件中的版本号即可。
// javascriptcn.com 代码示例 self.addEventListener('install', event => { console.log('[Service Worker] Installing Service Worker ...'); event.waitUntil( caches.open('static') .then(cache => { console.log('[Service Worker] Precaching App Shell'); cache.addAll([ '/', '/index.html', '/favicon.ico', '/manifest.webmanifest', '/styles.css', '/main.js' ]); }) ); self.skipWaiting(); }); self.addEventListener('activate', event => { console.log('[Service Worker] Activating Service Worker ...'); event.waitUntil( caches.keys().then(keyList => { return Promise.all(keyList.map(key => { if (key !== 'static') { console.log('[Service Worker] Removing old cache', key); return caches.delete(key); } })); }) ); self.clients.claim(); });
代码解释:
- 在 install 事件中,使用
self.skipWaiting()
方法跳过等待状态,立即激活新的 Service Worker; - 在 activate 事件中,使用
self.clients.claim()
方法立即激活新的 Service Worker; - 在 activate 事件中,删除旧版本的缓存。
总结
Service Worker 可以有效地提高 Web 应用的性能和用户体验,为我们提供了离线缓存、渐进增强、消息推送等功能。在 Angular SPA 应用中使用 Service Worker 需要使用 @angular/service-worker 模块来配置。实现离线缓存需要借助缓存 API 和 Service Worker 的 fetch 事件。为了保持 Service Worker 的最新代码,需要及时更新版本号。我们应该在开发 Web 应用时充分利用 Service Worker 提供的各种功能,为用户提供更好的体验。
参考资料
- Introduction to Service Workers
- @angular/service-worker documentation
- Using Service Workers to Make PWAs Work Offline
- Service Worker API
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6528ebfa7d4982a6ebb7a63d