”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 我如何在前端使用 Service Worker 优化加载时间

我如何在前端使用 Service Worker 优化加载时间

发布于2024-11-18
浏览:591

您是否遇到过网站加载时间过长的情况,如下图所示?

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]删除
最新教程 更多>
  • 如何高效地在一个事务中插入数据到多个MySQL表?
    如何高效地在一个事务中插入数据到多个MySQL表?
    mySQL插入到多个表中,该数据可能会产生意外的结果。虽然似乎有多个查询可以解决问题,但将从用户表的自动信息ID与配置文件表的手动用户ID相关联提出了挑战。使用Transactions和last_insert_id() 插入用户(用户名,密码)值('test','test...
    编程 发布于2025-05-25
  • Python读取CSV文件UnicodeDecodeError终极解决方法
    Python读取CSV文件UnicodeDecodeError终极解决方法
    在试图使用已内置的CSV模块读取Python中时,CSV文件中的Unicode Decode Decode Decode Decode decode Error读取,您可能会遇到错误的错误:无法解码字节 在位置2-3中:截断\ uxxxxxxxx逃脱当CSV文件包含特殊字符或Unicode的路径逃...
    编程 发布于2025-05-25
  • 如何使用Python有效地以相反顺序读取大型文件?
    如何使用Python有效地以相反顺序读取大型文件?
    在python 中,如果您使用一个大文件,并且需要从最后一行读取其内容,则在第一行到第一行,Python的内置功能可能不合适。这是解决此任务的有效解决方案:反向行读取器生成器 == ord('\ n'): 缓冲区=缓冲区[:-1] ...
    编程 发布于2025-05-25
  • 如何简化PHP中的JSON解析以获取多维阵列?
    如何简化PHP中的JSON解析以获取多维阵列?
    php 试图在PHP中解析JSON数据的JSON可能具有挑战性,尤其是在处理多维数组时。要简化过程,建议将JSON作为数组而不是对象解析。执行此操作,将JSON_DECODE函数与第二个参数设置为true:[&&&&& && &&&&& json = JSON = JSON_DECODE($ j...
    编程 发布于2025-05-25
  • PHP与C++函数重载处理的区别
    PHP与C++函数重载处理的区别
    作为经验丰富的C开发人员脱离谜题,您可能会遇到功能超载的概念。这个概念虽然在C中普遍,但在PHP中构成了独特的挑战。让我们深入研究PHP功能过载的复杂性,并探索其提供的可能性。在PHP中理解php的方法在PHP中,函数超载的概念(如C等语言)不存在。函数签名仅由其名称定义,而与他们的参数列表无关。...
    编程 发布于2025-05-25
  • 在PHP中如何高效检测空数组?
    在PHP中如何高效检测空数组?
    在PHP 中检查一个空数组可以通过各种方法在PHP中确定一个空数组。如果需要验证任何数组元素的存在,则PHP的松散键入允许对数组本身进行直接评估:一种更严格的方法涉及使用count()函数: if(count(count($ playerList)=== 0){ //列表为空。 } 对...
    编程 发布于2025-05-25
  • 用户本地时间格式及时区偏移显示指南
    用户本地时间格式及时区偏移显示指南
    在用户的语言环境格式中显示日期/时间,并使用时间偏移在向最终用户展示日期和时间时,以其localzone and格式显示它们至关重要。这确保了不同地理位置的清晰度和无缝用户体验。以下是使用JavaScript实现此目的的方法。方法:推荐方法是处理客户端的Javascript中的日期/时间格式化和时...
    编程 发布于2025-05-25
  • 如何将来自三个MySQL表的数据组合到新表中?
    如何将来自三个MySQL表的数据组合到新表中?
    mysql:从三个表和列的新表创建新表 答案:为了实现这一目标,您可以利用一个3-way Join。 选择p。*,d.content作为年龄 来自人为p的人 加入d.person_id = p.id上的d的详细信息 加入T.Id = d.detail_id的分类法 其中t.taxonomy =...
    编程 发布于2025-05-25
  • 版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    在时间戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源于遗留实现的关注,这些限制需要对当前的_timestamp功能进行特定的实现。 创建表`foo`( `Productid` int(10)unsigned not n...
    编程 发布于2025-05-25
  • `console.log`显示修改后对象值异常的原因
    `console.log`显示修改后对象值异常的原因
    foo = [{id:1},{id:2},{id:3},{id:4},{id:id:5},],]; console.log('foo1',foo,foo.length); foo.splice(2,1); console.log('foo2', foo, foo....
    编程 发布于2025-05-25
  • MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    在两个条件下插入或更新或更新 solution:的答案在于mysql的插入中...在重复键更新语法上。如果不存在匹配行或更新现有行,则此功能强大的功能可以通过插入新行来进行有效的数据操作。如果违反了唯一的密钥约束。实现所需的行为,该表必须具有唯一的键定义(在这种情况下为'名称'...
    编程 发布于2025-05-25
  • 如何使用PHP将斑点(图像)正确插入MySQL?
    如何使用PHP将斑点(图像)正确插入MySQL?
    essue VALUES('$this->image_id','file_get_contents($tmp_image)')";This code builds a string in PHP, but the function call ...
    编程 发布于2025-05-25
  • 如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    为有效的slug生成首先,该函数用指定的分隔符替换所有非字母或数字字符。此步骤可确保slug遵守URL惯例。随后,它采用ICONV函数将文本简化为us-ascii兼容格式,从而允许更广泛的字符集合兼容性。接下来,该函数使用正则表达式删除了不需要的字符,例如特殊字符和空格。此步骤可确保slug仅包含...
    编程 发布于2025-05-25
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中可能会遇到一个冲突,其中3派对软件包将另一个带有导入套件的path package the Imptioned package the Imptioned package the Imported tocted pac...
    编程 发布于2025-05-25

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3