Service Worker 是什么
Service Worker 是一個(gè)在瀏覽器中運(yùn)行的 JavaScript 腳本,它為Web應(yīng)用程序提供了一種在后臺(tái)執(zhí)行的機(jī)制。它的主要用途是處理離線緩存、推送通知、網(wǎng)絡(luò)請(qǐng)求攔截和消息傳遞等功能,這些功能可以改善Web應(yīng)用程序的性能和用戶體驗(yàn)。
Service Worker運(yùn)行在一個(gè)獨(dú)立的線程中,因此它不會(huì)阻塞主頁面的渲染和用戶交互,從而改善了性能。然而,由于它的強(qiáng)大功能和潛在的安全風(fēng)險(xiǎn),使用Service Worker需要小心謹(jǐn)慎,確保安全性和合理性。
Service Worker 主要特點(diǎn)和用途是什么那
離線緩存:Service Worker可以將網(wǎng)站資源(如HTML、CSS、JavaScript、圖像等)緩存到本地,使網(wǎng)站能夠在離線狀態(tài)下繼續(xù)運(yùn)行。這提供了更好的離線體驗(yàn),尤其在移動(dòng)設(shè)備上或網(wǎng)絡(luò)不穩(wěn)定的環(huán)境中。
網(wǎng)絡(luò)請(qǐng)求攔截:Service Worker可以攔截網(wǎng)頁發(fā)出的網(wǎng)絡(luò)請(qǐng)求,從緩存中獲取資源,或者將請(qǐng)求代理到服務(wù)器。這允許開發(fā)人員實(shí)施自定義的緩存策略,以提高性能和效率。
推送通知:Service Worker允許網(wǎng)站發(fā)送推送通知,即使網(wǎng)站并未打開在瀏覽器中。這對(duì)于實(shí)時(shí)通知用戶非常有用,例如新消息、提醒或更新。
后臺(tái)同步:Service Worker可以在后臺(tái)執(zhí)行任務(wù),例如數(shù)據(jù)同步或更新,而無需打開網(wǎng)站。這對(duì)于定期更新數(shù)據(jù)或執(zhí)行其他自動(dòng)化任務(wù)很有用。
消息傳遞:Service Worker可以與頁面之間以及與服務(wù)器進(jìn)行雙向通信,這為構(gòu)建高度交互性的Web應(yīng)用程序提供了便利。
Service Worker 生命周期是什么
- 注冊(cè):首次訪問頁面時(shí),瀏覽器會(huì)嘗試注冊(cè)一個(gè) Service Worker 腳本。你通常在頁面中使用 JavaScript 的
navigator.serviceWorker.register()
方法來進(jìn)行注冊(cè)。 - 安裝:當(dāng) Service Worker 腳本成功注冊(cè)時(shí),它會(huì)執(zhí)行
install
事件處理程序。在這個(gè)事件處理程序中,你可以緩存網(wǎng)站的靜態(tài)資源,以便在以后離線使用。通常,這個(gè)階段用于初始化 Service Worker。 - 激活:一旦 Service Worker 安裝成功,瀏覽器會(huì)嘗試激活新的 Service Worker。在激活階段,你可以執(zhí)行清理舊緩存、刪除不再需要的資源等操作。Service Worker 只有在成功激活后才能控制客戶端的網(wǎng)絡(luò)請(qǐng)求。
- 控制客戶端:一旦 Service Worker 被激活,它可以控制與之關(guān)聯(lián)的客戶端,包括網(wǎng)頁或其他客戶端。在這個(gè)階段,Service Worker 可以攔截網(wǎng)絡(luò)請(qǐng)求、處理推送通知、接收消息等。它會(huì)持續(xù)運(yùn)行,直到被注銷或停止。
- 更新:當(dāng)你更新 Service Worker 腳本時(shí),瀏覽器會(huì)檢測(cè)到新版本,并將其下載。新版本的 Service Worker 會(huì)經(jīng)歷安裝、激活和控制客戶端的階段,以確保平穩(wěn)的過渡。通常,你可以在新版本的 Service Worker 中更新緩存或執(zhí)行其他操作,以提供更好的用戶體驗(yàn)
- 注銷:Service Worker 可以被手動(dòng)注銷,或者在腳本中調(diào)用
self.skipWaiting()
方法來強(qiáng)制激活新版本。這可以用于確保新的 Service Worker 能夠立即控制客戶端,而不需要等待舊版本自然過期。
Service Worker 用法
Service Worker 如何注冊(cè)
注冊(cè) Service Worker:使用 navigator.serviceWorker.register()
方法注冊(cè) Service Worker。通常,這會(huì)在頁面加載時(shí)或在合適的時(shí)機(jī)執(zhí)行。
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then((registration) => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch((error) => {
console.error('Service Worker registration failed:', error);
});
}
在上述代碼中,navigator.serviceWorker.register('/service-worker.js')
會(huì)嘗試注冊(cè)位于根目錄下的 service-worker.js
文件作為 Service Worker。
處理注冊(cè)成功和失?。?code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 0.87em; word-break: break-word; border-radius: 2px; overflow-x: auto; background-color: rgb(255, 245, 245); color: rgb(255, 80, 44); padding: 0.065em 0.4em;">register() 方法返回一個(gè) Promise,可以使用 .then()
處理注冊(cè)成功的情況,以及使用 .catch()
處理注冊(cè)失敗的情況。在注冊(cè)成功后,你可以獲得一個(gè)包含有關(guān) Service Worker 注冊(cè)的信息的對(duì)象,如上述代碼所示。
請(qǐng)注意,Service Worker 必須位于與網(wǎng)頁相同的域中,以便進(jìn)行注冊(cè)。否則,由于安全策略的限制,Service Worker 無法注冊(cè)成功。
一旦 Service Worker 注冊(cè)成功,它將開始安裝并激活,然后可以開始控制與之關(guān)聯(lián)的客戶端(例如網(wǎng)頁),執(zhí)行緩存、網(wǎng)絡(luò)請(qǐng)求攔截、推送通知等任務(wù)。
Service Worker 如何控制客戶端
- 攔截和處理網(wǎng)絡(luò)請(qǐng)求:Service Worker 可以通過攔截客戶端發(fā)出的網(wǎng)絡(luò)請(qǐng)求來控制它們。你可以檢查請(qǐng)求,從緩存中獲取響應(yīng),或者將請(qǐng)求代理到服務(wù)器。這使你能夠?qū)崿F(xiàn)離線支持、緩存策略、網(wǎng)絡(luò)請(qǐng)求重試等功能。
例如,下面是一個(gè)攔截并從緩存中獲取資源的示例:
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
- 向客戶端發(fā)送消息:Service Worker 可以通過使用
postMessage
方法向客戶端發(fā)送消息??蛻舳丝梢员O(jiān)聽 message
事件以接收并響應(yīng)消息。 在 Service Worker 中發(fā)送消息:
self.clients.matchAll().then((clients) => {
clients.forEach((client) => {
client.postMessage('Hello from Service Worker!');
});
});
在客戶端中監(jiān)聽消息:
navigator.serviceWorker.addEventListener('message', (event) => {
console.log('Message from Service Worker:', event.data);
});
- 推送通知:Service Worker 可以用于處理推送通知,從服務(wù)器發(fā)送通知到客戶端。一旦推送通知到達(dá),Service Worker 可以展示通知或執(zhí)行其他操作,以提醒用戶或執(zhí)行相關(guān)任務(wù)。
self.addEventListener('push', (event) => {
const options = {
body: event.data.text(),
icon: '/icon.png',
};
event.waitUntil(
self.registration.showNotification('Push Notification', options)
);
});
- 同步任務(wù):Service Worker 還支持后臺(tái)同步,這意味著它可以在客戶端離線時(shí)執(zhí)行任務(wù),然后在網(wǎng)絡(luò)連接可用時(shí)同步數(shù)據(jù)。
例如,你可以使用后臺(tái)同步來上傳離線時(shí)保存的數(shù)據(jù)到服務(wù)器:
self.addEventListener('sync', (event) => {
if (event.tag === 'sync-task') {
event.waitUntil(doSyncTask());
}
});
Service Worker 如何注銷
要注銷(解除注冊(cè))一個(gè) Service Worker,你可以使用 navigator.serviceWorker.getRegistration()
和 unregister()
方法。這允許你手動(dòng)取消注冊(cè)一個(gè) Service Worker。 以下是一些步驟來注銷 Service Worker: 獲取 Service Worker 的注冊(cè):
- 首先,你需要獲取當(dāng)前已注冊(cè)的 Service Worker。你可以使用
navigator.serviceWorker.getRegistration()
方法來獲取 Service Worker 的注冊(cè)對(duì)象。這將返回一個(gè) Promise,包含 Service Worker 的注冊(cè)信息。
navigator.serviceWorker.getRegistration()
.then((registration) => {
if (registration) {
}
});
- 注銷 Service Worker:
navigator.serviceWorker.getRegistration()
.then((registration) => {
if (registration) {
registration.unregister()
.then((isUnregistered) => {
if (isUnregistered) {
console.log('Service Worker unregistered successfully.');
} else {
console.log('Service Worker was not unregistered.');
}
})
.catch((error) => {
console.error('Error while trying to unregister the Service Worker:', error);
});
}
});
Service Worker 調(diào)試以及檢查
service worker實(shí)際上提供的是本地緩存服務(wù),所以和我們平時(shí)查看localStorage差不多,打開谷歌瀏覽
器調(diào)試中心,在Application欄下,就能看到Service Woerkers,如圖:

也可以通過右側(cè) 取消注冊(cè) 以及更新 進(jìn)行手動(dòng)觸發(fā)
我們可以通過網(wǎng)絡(luò)請(qǐng)求看到當(dāng)前請(qǐng)求的一個(gè)狀態(tài)

Service Worker 和其他緩存(如瀏覽器緩存、Web Storage、IndexedDB 等)之間有一些關(guān)鍵區(qū)別
- 位置
- Service Worker 是一個(gè)在瀏覽器后臺(tái)運(yùn)行的 JavaScript 腳本,它能夠攔截和處理網(wǎng)絡(luò)請(qǐng)求,以及緩存響應(yīng)數(shù)據(jù)。它通常用于實(shí)現(xiàn)離線緩存、推送通知和其他高級(jí)功能。
- 瀏覽器緩存、Web Storage 和 IndexedDB 等是在瀏覽器前臺(tái)運(yùn)行的緩存機(jī)制,它們通常用于存儲(chǔ)靜態(tài)資源(如圖片、CSS、JavaScript)、用戶數(shù)據(jù)和應(yīng)用程序狀態(tài)。
- 用途:
- Service Worker 的主要目的是提供離線支持、網(wǎng)絡(luò)請(qǐng)求攔截、推送通知和后臺(tái)同步等功能,從而增強(qiáng) Web 應(yīng)用程序的性能和用戶體驗(yàn)。
- 瀏覽器緩存 用于存儲(chǔ)靜態(tài)資源,以減少資源加載時(shí)間和帶寬消耗。
- Web Storage 和 IndexedDB 通常用于存儲(chǔ)應(yīng)用程序的用戶數(shù)據(jù)、會(huì)話信息和應(yīng)用程序狀態(tài)。
- 網(wǎng)絡(luò)請(qǐng)求控制:
- Service Worker 具有強(qiáng)大的網(wǎng)絡(luò)請(qǐng)求控制能力,它可以攔截和處理網(wǎng)絡(luò)請(qǐng)求,從緩存中獲取響應(yīng),甚至將請(qǐng)求代理到服務(wù)器。
- 瀏覽器緩存 通常依賴于瀏覽器的默認(rèn)緩存策略,但可以通過 HTTP 標(biāo)頭進(jìn)行控制。
- Web Storage 和 IndexedDB 不直接與網(wǎng)絡(luò)請(qǐng)求相關(guān),而是用于本地存儲(chǔ)數(shù)據(jù)。
- 離線支持:
- Service Worker 是設(shè)計(jì)用來提供離線支持的,它可以使網(wǎng)頁在離線狀態(tài)下仍然能夠運(yùn)行。
- 瀏覽器緩存 通常緩存靜態(tài)資源,但不提供離線支持。
- Web Storage 和 IndexedDB 也不提供離線支持,它們依賴于瀏覽器的在線狀態(tài)。
- 事件驅(qū)動(dòng):總的來說,Service Worker 是一個(gè)強(qiáng)大的工具,可用于增強(qiáng) Web 應(yīng)用程序的性能和功能,特別是在離線和實(shí)時(shí)通知方面。其他緩存機(jī)制通常用于存儲(chǔ)靜態(tài)資源和用戶數(shù)據(jù),但它們不提供 Service Worker 的高級(jí)功能。在開發(fā) Web 應(yīng)用程序時(shí),你可以根據(jù)需求選擇合適的緩存機(jī)制。
轉(zhuǎn)自?https://juejin.cn/post/7291502663106772992
該文章在 2025/9/6 17:00:03 編輯過