」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 我如何在前端使用 Service Worker 最佳化載入時間

我如何在前端使用 Service Worker 最佳化載入時間

發佈於2024-11-18
瀏覽:143

您是否遇到過網站載入時間過長的情況,如下圖所示?

How I optimized loading time using service workers in frontend

?你聽過服務人員嗎?

在這篇文章中,我們將深入探討什麼是 Service Worker? 、它們如何運作 ⚙️,以及我如何使用它們來提高 Web 應用程式的效能。


什麼是 Service Worker? ?

Service Worker 是一個獨立於網頁運行的後台腳本,可以:

  • 快取資源? ️
  • 攔截網路請求?
  • 提供離線功能?

Service Workers 的主要特徵:

  1. 在背景運行:Service Worker 不依賴頁面的生命週期,這意味著即使頁面關閉,它們也可以繼續運行
  2. 事件驅動:Service Worker監聽特定事件,例如網路請求(取得事件)
  3. 無 DOM 存取權:與其他 Web Worker 不同,Service Worker 無法直接存取 DOM。它們在後台運行,管理資源和網路流量

這是 Service Worker 腳本的簡單範例:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
      console.log('Service Worker registered with scope:', registration.scope);
    }).catch(function(error) {
      console.error('Service Worker registration failed:', error);
    });
  });
}

?在此程式碼片段中,服務工作執行緒 (service-worker.js) 在頁面載入時註冊。如果註冊成功,它會記錄 Service Worker 的範圍;否則,它會記錄錯誤。


我的挑戰:將 Unity WebGL 遊戲整合到網頁中

我正在將 Unity WebGL 遊戲整合到 .NET Razor 網站中。遊戲由大型「.wasm」和「.data」檔案以及對於遊戲載入至關重要的 JavaScript 檔案組成。然而,第一次加載頁面花了20多秒! ?這主要是由於“.wasm”和“.data”檔案的大小所造成的。


解決方案:使用 Service Worker 進行快取

我創建了一個“ServiceWorker.js”文件,它緩存所有必要的遊戲資源以減少加載時間。該文件包含以下內容:

const cacheName = "$Project_name";
const contentToCache = [
    "Build/Game.loader.js",
    "Build/Game.framework.js",
    "Build/Game.data",
    "Build/Game.wasm",
    "TemplateData/game_style.css"
];

self.addEventListener('install', function (e) {
    console.log('[Service Worker] Install');

    e.waitUntil((async function () {
        try {
            const cache = await caches.open(cacheName);
            console.log('[Service Worker] Caching all: app shell and content');
            for (const resource of contentToCache) {
                try {
                    await cache.add(resource);
                } catch (error) {
                    console.error(`[Service Worker] Failed to cache: ${resource}`, error);
                }
            }
        } catch (error) {
            console.error('[Service Worker] Failed to open cache', error);
        }
    })());
});

self.addEventListener('fetch', function (e) {
     e.respondWith((async function () {
        try {
            const response = await caches.match(e.request);
            console.log(`[Service Worker] Fetching resource: ${e.request.url}`);
            if (response) return response;

            const fetchResponse = await fetch(e.request);
            const cache = await caches.open(cacheName);
            console.log(`[Service Worker] Caching new resource: ${e.request.url}`);
            await cache.put(e.request, fetchResponse.clone());
            return fetchResponse;
        } catch (error) {
            console.error(`[Service Worker] Error fetching resource: ${e.request.url}`, error);
            throw error;
        }
    })());
});

這段程式碼的作用是什麼?

此服務工作執行緒腳本執行下列操作:

  • 快取遊戲運作所需的基本文件,包括安裝階段的「.wasm」、「.data」和JS檔案。
  • 攔截獲取請求以提供快取資源(如果可用)。如果資源不在快取中,它將從網路取得、快取並回傳回應。

結果:性能顯著提升

透過快取這些資源,載入時間從 20 秒減少到 3 秒以下?當用戶下次造訪該頁面時,資產已經儲存在本地,大大加快了體驗速度。

⚠️要小心!快取問題

雖然這種方法對於提高效能有奇效,但它引入了另一個問題:過時的快取檔案。由於我們正在積極開發Unity遊戲並發布新版本,因此每次部署新版本時都需要清除快取檔案。

為了解決這個問題,我創建了一個管道腳本,每當我們發布新的遊戲版本時,它都會自動取消註冊舊的服務工作者並清除快取。這可確保使用者始終載入最新的資源,而不會被舊的快取版本所困擾。


結論

在 Web 應用程式中實現 Service Worker 可以顯著提高效能,尤其是在處理大型資源(例如在我的 Unity WebGL 遊戲中)時。然而,重要的是仔細處理快取以避免提供過時的檔案。

您在優化載入時間方面有類似的經驗嗎?您使用了服務人員或其他技術嗎?在下面的評論中分享您的想法和見解! ?

希望您今天學到新東西了! ✌️

版本聲明 本文轉載於:https://dev.to/perisicnikola37/how-i-optimized-loading-time-using-service-workers-in-frontend-2lk9?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • Java中線程引用設定為Null時會產生垃圾嗎?
    Java中線程引用設定為Null時會產生垃圾嗎?
    Java 主題:垃圾收集與否? 在此 Java 程式碼片段中,建立了一個新線程,並使用 t.start( )。但是,啟動線程後,線程引用 t 被設定為 null,且 t = null。這就提出了一個問題:在沒有主動引用線程的情況下,線程是否會被垃圾收集。 Java 中的垃圾收集當垃圾收集器在 Jav...
    程式設計 發佈於2024-11-18
  • 儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    解決PHP 中的POST 請求故障在提供的程式碼片段中:action=''而非:action="<?php echo $_SERVER['PHP_SELF'];?>";?>"檢查$_POST陣列:表單提交後使用 var_dump 檢查 $_POST 陣列的內...
    程式設計 發佈於2024-11-18
  • 如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    在 PHP 中組合關聯數組在 PHP 中,將兩個關聯數組組合成一個數組是常見任務。考慮以下請求:問題描述:提供的代碼定義了兩個關聯數組,$array1 和 $array2。目標是建立一個新陣列 $array3,它合併兩個陣列中的所有鍵值對。 此外,提供的陣列具有唯一的 ID,而名稱可能重疊。要求是建...
    程式設計 發佈於2024-11-18
  • 為什麼我的 Python MySQL 插入不起作用?
    為什麼我的 Python MySQL 插入不起作用?
    Python MySQL 插入操作疑難解答在 Python 中,使用 MySQL API 與 MySQL 資料庫交互,插入記錄可能會遇到障礙。本文解決了這樣一個問題:儘管實現看似正確,但記錄卻無法插入。 提供的程式碼建立了與資料庫的連接,並嘗試將記錄插入「文件」表中。但是,插入操作失敗。要解決這個問...
    程式設計 發佈於2024-11-18
  • 大批
    大批
    方法是可以在物件上呼叫的 fns 數組是對象,因此它們在 JS 中也有方法。 slice(begin):將陣列的一部分提取到新數組中,而不改變原始數組。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index ...
    程式設計 發佈於2024-11-18
  • 為什麼 C++ 建構函式有兩個符號?
    為什麼 C++ 建構函式有兩個符號?
    C 建構子的雙重符號Itanium C ABI 指定建構函式的重整名稱包含有關其型別和參數的資訊。因此,在庫中觀察到的兩個建構函式條目源自於它們不同的建構子類型:完整物件建構子(C1):此建構子完全初始化對象,包括任何虛擬基類.基對象構造函數(C2): 此構造函數初始化對象本身以及資料成員和非虛擬基...
    程式設計 發佈於2024-11-18
  • Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta:列偏移的刪除和恢復Bootstrap 4 在其Beta 1 版本中引入了重大更改柱子偏移了。然而,隨著 Beta 2 的後續發布,這些變化已經逆轉。 從 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    程式設計 發佈於2024-11-18
  • WaitGroup.Wait() 回傳後檢查共享變數是否安全?
    WaitGroup.Wait() 回傳後檢查共享變數是否安全?
    WaitGroup.Wait() 和記憶體屏障在存取共享變數的多執行緒環境中,強制同步至關重要以防止出現意外結果。 Go 中的一種此類機制是「sync.WaitGroup」包,它有助於管理並發運行的 goroutine。 目前的問題圍繞著「WaitGroup.Wait()」和記憶體屏障之間的關係展開...
    程式設計 發佈於2024-11-18
  • 在 C++ 中如何將浮點數精確轉換為具有指定十進位精確度的字串?
    在 C++ 中如何將浮點數精確轉換為具有指定十進位精確度的字串?
    將浮點數精確轉換為具有指定十進制精度的字串在C 中,將浮點數轉換為具有特定精度的字串,並且小數位需要仔細考慮。本指南探討了兩種常見的解:stringstream 和 C 17 中的 to_chars 函數。 使用 StringstreamStringstream 是 C 中操作字串的多功能工具。要將...
    程式設計 發佈於2024-11-18
  • \“需要協助修改預設行事曆選擇器的 UI\”
    \“需要協助修改預設行事曆選擇器的 UI\”
    嗨,團隊,我在 AG 網格單元中使用日曆,但我無法修改此日曆的 UI,也無法檢查它。我想更改日曆的 UI。 請參閱連結以取得更多說明 https://www.ag-grid.com/examples/provided-cell-editors-date/date-editor/modules/ty...
    程式設計 發佈於2024-11-18
  • 為什麼我在 MySQL 中收到「寫入檔案『/tmp/MY1fnqpm』時出錯(錯誤代碼:28)」?
    為什麼我在 MySQL 中收到「寫入檔案『/tmp/MY1fnqpm』時出錯(錯誤代碼:28)」?
    MySQL 檔案寫入錯誤(Errcode 28):診斷與解決遇到錯誤「Errorwriting file '/tmp/MY1fnqpm' ( Errcode: 28)」 在MySQL 查詢中,根本原因通常在於可用磁碟空間不足。要確認這一點,請使用 perror 指令:$ perror...
    程式設計 發佈於2024-11-18
  • 在 Go 中使用 WebSocket 進行即時通信
    在 Go 中使用 WebSocket 進行即時通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    程式設計 發佈於2024-11-18
  • 如何使用 Sequelize CLI 從 Sequelize 模型產生遷移?
    如何使用 Sequelize CLI 從 Sequelize 模型產生遷移?
    使用Sequelize CLI 從Sequelize 模型自動產生遷移人們可能擁有預先存在的Sequelize 模型,但希望使用遷移而不是資料庫同步。 Sequelize CLI 提供了一篇文章中概述的解決方案,其中指出,「當利用CLI 進行模型生成時,您將自動獲取必要的遷移腳本。」要實現此任務: ...
    程式設計 發佈於2024-11-18
  • 為什麼Selenium 2.53.0在使用Firefox 47時會遇到連線錯誤?
    為什麼Selenium 2.53.0在使用Firefox 47時會遇到連線錯誤?
    Selenium 2.53 與Firefox 47 不相容使用Selenium WebDriver 2.53.0 時,遇到錯誤:org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1...
    程式設計 發佈於2024-11-18

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3