SvelteKit 最新中文文档教程(16)—— Service workers

前言

Svelte,一个语法简洁、入门容易,面向未来的前端框架。

从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:

image.png

Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构建轻量级 Web 项目。

为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。

如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!

欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。

Service workers

Service workers 作为代理服务端,处理应用程序内部的网络请求。这使得您的应用程序能够离线工作,但即使您不需要离线支持(或由于您正在构建的应用程序类型而无法实现它),使用 service workers 预缓存构建的 JS 和 CSS 来加快导航速度,通常也是值得的。

在 SvelteKit 中,如果您有一个 src/service-worker.js 文件(或 src/service-worker/index.js),它将被打包并自动注册。如果需要,您可以更改 service worker 的位置。

如果您需要使用自己的逻辑注册 service worker 或使用其他解决方案,可以禁用自动注册。默认注册看起来类似这样:

1if ('serviceWorker' in navigator) { 2 addEventListener('load', function () { 3 navigator.serviceWorker.register('./path/to/service-worker.js'); 4 }); 5}

Service Worker 内部

在 service worker 内部,您可以访问 $service-worker 模块,它为您提供所有静态资源、构建文件和预渲染页面的路径。您还会获得一个应用程序版本字符串,可用于创建唯一的缓存名称,以及部署的 base 路径。如果您的 Vite 配置指定了 define(用于全局变量替换),这也将应用于 service workers 以及服务端/客户端构建。

以下示例会尽可能早的缓存构建的应用程序和 static 中的所有文件,并在访问时缓存所有其他请求。这将使每个页面在访问后都能离线工作。

1// @errors: 2339 2/// <reference types="@sveltejs/kit" /> 3import { build, files, version } from '$service-worker'; 4 5// 为此部署创建唯一的缓存名称 6const CACHE = `cache-${version}`; 7 8const ASSETS = [ 9 ...build, // 应用程序本身 10 ...files // `static` 中的所有内容 11]; 12 13self.addEventListener('install', (event) => { 14 // 创建新缓存并添加所有文件 15 async function addFilesToCache() { 16 const cache = await caches.open(CACHE); 17 await cache.addAll(ASSETS); 18 } 19 20 event.waitUntil(addFilesToCache()); 21}); 22 23self.addEventListener('activate', (event) => { 24 // 从磁盘删除以前的缓存数据 25 async function deleteOldCaches() { 26 for (const key of await caches.keys()) { 27 if (key !== CACHE) await caches.delete(key); 28 } 29 } 30 31 event.waitUntil(deleteOldCaches()); 32}); 33 34self.addEventListener('fetch', (event) => { 35 // 忽略 POST 请求等 36 if (event.request.method !== 'GET') return; 37 38 async function respond() { 39 const url = new URL(event.request.url); 40 const cache = await caches.open(CACHE); 41 42 // `build`/`files` 始终可以从缓存中提供服务 43 if (ASSETS.includes(url.pathname)) { 44 const response = await cache.match(url.pathname); 45 46 if (response) { 47 return response; 48 } 49 } 50 51 // 对于其他所有内容,首先尝试网络 52 // 但如果我们离线,则回退到缓存 53 try { 54 const response = await fetch(event.request); 55 56 // 如果我们离线,fetch 可能返回非 Response 值 57 // 而不是抛出错误 - 我们不能将这个非 Response 传递给 respondWith 58 if (!(response instanceof Response)) { 59 throw new Error('invalid response from fetch'); 60 } 61 62 if (response.status === 200) { 63 cache.put(event.request, response.clone()); 64 } 65 66 return response; 67 } catch (err) { 68 const response = await cache.match(event.request); 69 70 if (response) { 71 return response; 72 } 73 74 // 如果没有缓存,就直接报错 75 // 因为我们无法对这个请求做任何响应 76 throw err; 77 } 78 } 79 80 event.respondWith(respond()); 81});

[!NOTE] 缓存时要小心!在某些情况下,过时的数据可能比离线时无法获取的数据更糟糕。由于浏览器会在缓存太满时清空缓存,因此您还应该谨慎缓存大型资源,如视频文件。

在开发过程中

service worker 在生产环境中会被打包,但在开发过程中不会。因此,只有支持 service workers 中的模块 的浏览器才能在开发时使用它们。如果您手动注册 service worker,在开发时需要传递 { type: 'module' } 选项:

1import { dev } from '$app/environment'; 2 3navigator.serviceWorker.register('/service-worker.js', { 4 type: dev ? 'module' : 'classic' 5});

[!NOTE] 在开发环境中,build 和 prerendered 是空数组

类型安全

为 service workers 设置适当的类型需要一些手动设置。在您的 service-worker.js 中,在文件顶部添加以下内容:

1/// <reference types="@sveltejs/kit" /> 2/// <reference no-default-lib="true"/> 3/// <reference lib="esnext" /> 4/// <reference lib="webworker" /> 5 6const sw = /** @type {ServiceWorkerGlobalScope} */ (/** @type {unknown} */ (self));
1/// <reference types="@sveltejs/kit" /> 2/// <reference no-default-lib="true"/> 3/// <reference lib="esnext" /> 4/// <reference lib="webworker" /> 5 6const sw = self as unknown as ServiceWorkerGlobalScope;

这会禁用对 service worker 中不可用的 DOM 类型(如 HTMLElement)的访问,并实例化正确的全局变量。将 self 重新赋值给 sw 允许您在此过程中进行类型转换(有几种方法可以做到这一点,但这是最简单的,不需要额外的文件)。在文件的其余部分使用 sw 而不是 self。

对 SvelteKit 类型的引用确保 $service-worker 导入具有适当的类型定义。如果您导入 $env/static/public,您要么必须使用 // @ts-ignore 注释导入,要么添加 /// <reference types="../.svelte-kit/ambient.d.ts" /> 到引用类型中。

其他解决方案

SvelteKit 的 service worker 实现故意保持低级别。如果您需要更全功能但也更有主见的解决方案,我们建议查看像 Vite PWA 插件 这样的解决方案,它使用 Workbox。有关 service workers 的更多一般信息,我们推荐 MDN web 文档。

Svelte 中文文档

点击查看中文文档:SvelteKit Service workers

系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!

此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog

欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。

点赞
收藏

评论区

加载中...

相关推荐

Svelte 最新中文文档教程(21)—— 自定义元素

前言,一个语法简洁、入门容易,面向未来的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非

Svelte 最新中文文档教程(22)—— Svelte 5 迁移指南

前言,一个语法简洁、入门容易,面向未来的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非

SvelteKit 最新中文文档教程(1)—— 入门指南

前言,一个语法简洁、入门容易,面向未来的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非

SvelteKit 最新中文文档教程(2)—— 路由

前言,一个语法简洁、入门容易,面向未来的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非

SvelteKit 最新中文文档教程(3)—— 数据加载

前言,一个语法简洁、入门容易,面向未来的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非

SvelteKit 最新中文文档教程(4)—— 表单 actions

前言,一个语法简洁、入门容易,面向未来的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非