進階
服務工作人員
在 GitHub 上編輯此頁面服務工作人員扮演代理伺服器的角色,處理應用程式內的網路要求。這讓你的應用程式可以離線運作,但即使你不需要離線支援(或因為你正在建構的應用程式類型而無法實際實作),使用服務工作人員來透過預先快取已建置的 JS 和 CSS 來加速導覽通常是值得的。
在 SvelteKit 中,如果你有 src/service-worker.js
檔案(或 src/service-worker/index.js
),它將會被綑綁並自動註冊。如果你需要的話,可以變更 服務工作人員的位置。
如果你需要使用自己的邏輯註冊服務工作人員或使用其他解決方案,你可以 停用自動註冊。預設的註冊看起來像這樣
ts
if ('serviceWorker' innavigator ) {addEventListener ('load', function () {navigator .serviceWorker .register ('./path/to/service-worker.js');});}
在服務工作人員內部永久連結
在服務工作人員內部,你可以存取 $service-worker
模組,它會提供所有靜態資源、建置檔案和預先渲染頁面的路徑。你還會獲得一個應用程式版本字串,你可以使用它來建立一個唯一的快取名稱,以及部署的 base
路徑。如果你的 Vite 設定指定 define
(用於全域變數替換),這將會套用於服務工作人員以及你的伺服器/用戶端建置。
以下範例會積極快取已建置的應用程式和 static
中的任何檔案,並在它們發生時快取所有其他要求。這會讓每個頁面在造訪一次後都能離線運作。
ts
/// <reference types="@sveltejs/kit" />import {build ,files ,version } from '$service-worker';// Create a unique cache name for this deploymentconstCACHE = `cache-${version }`;constASSETS = [...build , // the app itself...files // everything in `static`];self .addEventListener ('install', (event ) => {// Create a new cache and add all files to itasync functionaddFilesToCache () {constProperty 'waitUntil' does not exist on type 'Event'.2339Property 'waitUntil' does not exist on type 'Event'.cache = awaitcaches .open (CACHE );awaitcache .addAll (ASSETS );}event .waitUntil (addFilesToCache ());});self .addEventListener ('activate', (event ) => {// Remove previous cached data from diskasync functiondeleteOldCaches () {for (constkey of awaitcaches .keys ()) {if (Property 'waitUntil' does not exist on type 'Event'.2339Property 'waitUntil' does not exist on type 'Event'.key !==CACHE ) awaitcaches .delete (key );}}event .waitUntil (deleteOldCaches ());});Property 'request' does not exist on type 'Event'.2339Property 'request' does not exist on type 'Event'.self .addEventListener ('fetch', (event ) => {// ignore POST requests etcProperty 'request' does not exist on type 'Event'.2339Property 'request' does not exist on type 'Event'.if (event .request .method !== 'GET') return;async functionrespond () {consturl = newURL (event .request .url );constcache = awaitcaches .open (CACHE );// `build`/`files` can always be served from the cacheif (ASSETS .includes (url .pathname )) {constresponse = awaitcache .match (url .pathname );if (response ) {returnresponse ;}}Property 'request' does not exist on type 'Event'.2339Property 'request' does not exist on type 'Event'.// for everything else, try the network first, but// fall back to the cache if we're offlinetry {constresponse = awaitfetch (event .request );// if we're offline, fetch can return a value that is not a Response// instead of throwing - and we can't pass this non-Response to respondWithif (!(response instanceofResponse )) {throw newProperty 'request' does not exist on type 'Event'.2339Property 'request' does not exist on type 'Event'.Error ('invalid response from fetch'); }if (response .status === 200) {cache .put (event .request ,response .clone ());}Property 'request' does not exist on type 'Event'.2339Property 'request' does not exist on type 'Event'.returnresponse ;} catch (err ) {constresponse = awaitcache .match (event .request );if (response ) {returnresponse ;}// if there's no cache, then just error out// as there is nothing we can do to respond to this requestthrowProperty 'respondWith' does not exist on type 'Event'.2339Property 'respondWith' does not exist on type 'Event'.err ;}}event .respondWith (respond ());});
小心快取!在某些情況下,過期的資料可能比離線時無法取得的資料更糟。由於瀏覽器會在快取過滿時清空快取,因此你還應小心快取大型資產,例如影片檔案。
開發期間永久連結
服務工作人員已打包用於生產,但開發期間並未打包。因此,只有支援服務工作人員中模組的瀏覽器才能在開發時間使用它們。如果你手動註冊服務工作人員,則需要在開發中傳遞選項{ type: 'module' }
ts
import {dev } from '$app/environment';navigator .serviceWorker .register ('/service-worker.js', {type :dev ? 'module' : 'classic'});
build
和prerendered
在開發期間為空陣列
類型安全性永久連結
為服務工作人員設定適當的類型需要一些手動設定。在 service-worker.js
內,將下列內容新增到檔案頂端
ts
/// <reference types="@sveltejs/kit" />/// <reference no-default-lib="true"/>/// <reference lib="esnext" />/// <reference lib="webworker" />constsw = /** @type {ServiceWorkerGlobalScope} */ (/** @type {unknown} */ (self ));
ts
/// <reference types="@sveltejs/kit" />/// <reference no-default-lib="true"/>/// <reference lib="esnext" />/// <reference lib="webworker" />constsw =self as unknown asServiceWorkerGlobalScope ;
這會停用對 DOM 型別的存取,例如 HTMLElement
,這些型別在服務工作人員內不可用,並實例化正確的全局變數。將 self
重新指派給 sw
允許你在處理過程中對其進行類型轉換(有幾種方法可以做到這一點,但這是最簡單的方法,不需要額外的檔案)。在檔案的其餘部分使用 sw
而不是 self
。對 SvelteKit 型別的參考可確保 $service-worker
匯入具有適當的類型定義。如果你匯入 $env/static/public
,則必須對匯入執行 // @ts-ignore
或將 /// <reference types="../.svelte-kit/ambient.d.ts" />
新增到參考類型。
其他解決方案永久連結
SvelteKit 的服務工作人員實作故意採用低層級。如果你需要更完善但意見也更多的解決方案,我們建議查看 Vite PWA 外掛程式 等解決方案,它使用 Workbox。有關服務工作人員的更一般資訊,我們建議 MDN 網路文件。