[译] JS 中 service workers 的简介

简介: Service workers是Progressive Web Apps的核心部分,允许缓存资源和Web推送通知等,以创建良好的离线体验。它们充当Web应用程序,浏览器和网络之间的代理,允许开发人员拦截和缓存网络请求,并基于网络的可用性采取适当的操作。

Service workersProgressive Web Apps的核心部分,允许缓存资源和Web推送通知等,以创建良好的离线体验。它们充当Web应用程序,浏览器和网络之间的代理,允许开发人员拦截和缓存网络请求,并基于网络的可用性采取适当的操作。


一个service worker在单独的线程上运行,因此它是非阻塞的。这也意味着它无法访问主JavaScript线程中可用的DOM和其他API,比如cookie,XHR,Web存储API(本地存储和会话存储)等。由于它们被设计为完全异步,因此它们重度依赖promise来等待网络请求的响应。


出于安全考虑,service workers仅使用HTTPS运行,且不能在隐私浏览模式下使用。但是,在发出本地请求的时候,你不需要安全连接(这足以进行测试)。


浏览器支持


Service Workers是一种相对较新的API,仅受现代浏览器的支持。因此,我们首先需要检查浏览器是否支持该API:


if('serviceWorker' in navigator) {
    // Supported 😍
} else {
    // Not supported 😥
}


Service Worker 注册


在我们开始缓存资源或拦截网络请求之前,我们必须在浏览器中安装service worker。由于service worker本质上是一个JavaScript文件,因此可以通过指定文件的路径来注册它。该文件必须可以通过网络访问,并且只应包含service worker代码。


你应该等待页面加载完成,然后将service worker文件路径传给navigator.serviceWorker.register()方法:


window.addEventListener('load', () => {
    if ('serviceWorker' in navigator) {
        // register service worker
        navigator.serviceWorker.register('/sw-worker.js').then(
            () => {
                console.log('SW registration succesful 😍');
            },
            err => {
                console.error('SW registration failed 😠', err)
            });
    } else {
        // Not supported 😥
    }
});


每次页面加载时都可以运行上面的代码,没有任何问题;浏览器将决定是否已经安装service worker并相应地处理它。


Service Worker 生命周期


注册生命周期包括三个步骤:


  1. 下载


  1. 安装


  1. 激活


当用户首次访问您的网站时,会立即下载service worker文件并尝试安装。如果安装成功,则激活service worker。在用户访问另一个页面后刷新当前页面之前,service worker文件中的任何功能都不可用。


浏览器事件


一旦service worker被安装并激活了,它就可以开始拦截网络请求和缓存资源。这可以通过监听service worker文件中浏览器发出的事件来完成。浏览器发出以下事件:


  • install 当安装service worker程序时将发出install
  • activate 成功注册和安装service worker程序后将发送active。在安装新版本之前,此事件可用于删除过期的缓存资源。
  • fetch 只要网页请求网络资源,就会发出fetch。资源可以是任何东西:新的HTML文档,图像,JSON API,样式表或者JavaScript文件,以及远程位置上可用的任何内容。
  • push 当收到新的推送通知时,push由Push API发送。你可以使用此事件向用户显示通知
  • sync 当浏览器在连接丢失后检测到网络可用性时,将掉哟个sync


提供缓存资源


我们可以在安装service worker时监听install事件,以缓存当我们离开网络时需要为网页提供服务的特定资源:


const CACHE_NAME = 'site-name-cache';
self.addEventListener('install', event => {
    event.waitUntil(
        caches
            .open(CACHE_NAME)
            .then(cache =>
                cache.addAll([
                    'favicon.ico',
                    'projects.json',
                    'style.css',
                    'index.js',
                    'https://fonts.googleapis.com/css?family=Open+Sans:400,700'
                ])
            )
    );
});


上面的例子中,代码使用Cache API将资源存储在名为site-name-cache的缓存中。


self关键字是一个只读的全局属性,service workers使用它来访问自己。


现在让我们监听一个fetch事件来检查所请求的资源是否已经存储在缓存中,如果找到则将其返回:


// ...
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            if (response) {
                //found cached resource
                return response;
            }
            return fetch(event.request);
        })
    );
});


我们查找请求属性标识的资源缓存条目,如果没有找到,我们会发送获取请求。如果你也想缓存新的请求,可以通过处理获取请求的响应然后将其添加到缓存来完成,如下所示:


// ...
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            if (response) {
                //found cached resource
                return response;
            }
            // get resource and add it to cache
            return fetch(event.request)
                .then(response => {
                    // check if the response is valid
                    if (!response.ok) {
                        return response;
                    }
                    // clone the response
                    const newResponse = response.clone();
                    // add it to cache
                    caches.open(CACHE_NAME)
                        .then(cache =>
                            cache.put(event.request, newResponse)
                        );
                    // return response
                    return response;
                });
        })
    );
});


Service Worker 更新


安装service worker程序后,它将继续运行,直到用户将其删除或者更新为止。要更新service worker,你需要做的就是在服务器上上传新版本的service worker文件。当用户访问你的站点时,浏览器将自动检测文件更改(即使只有一个字节更改就足够了),并安装新版本。


就像第一次安装一样,只有当用户导航到另一个页面或刷新当前页面时,新的service worker的功能才能使用。


我们可以做的事情就是监听activate事件,并删除旧的缓存资源。以下代码通过遍历所有缓存并删除与缓存名称匹配的缓存来完成此操作:


// ...
self.addEventListener('activate', event => {
    event.waitUntil(
        caches.keys().then(keys => {
            return Promise.all(
                keys.map(cache => {
                    if (cache === CACHE_NAME) {
                        return caches.delete(cache);
                    }
                })
            );
        })
    );
});


以上就是service workers的简介了。如果你想了解更多,移步SerciceWorker Cookbook -- 这里有一系列现代网站中使用service worker的实用例子。




相关文章
|
资源调度 JavaScript Linux
【Azure 应用服务】本地Node.js部署上云(Azure App Service for Linux)遇到的三个问题解决之道
【Azure 应用服务】本地Node.js部署上云(Azure App Service for Linux)遇到的三个问题解决之道
156 1
|
11月前
|
存储 JavaScript NoSQL
Node.js新作《循序渐进Node.js企业级开发实践》简介
《循序渐进Node.js企业级开发实践》由清华大学出版社出版,基于Node.js 22.3.0编写,包含26个实战案例和43个上机练习,旨在帮助读者从基础到进阶全面掌握Node.js技术,适用于初学者、进阶开发者及全栈工程师。
196 9
|
JavaScript 前端开发
JavaScript简介
JavaScript简介
|
Web App开发 JavaScript 前端开发
JavaWeb 22.Node.js_简介和安装
JavaWeb 22.Node.js_简介和安装
|
JavaScript 前端开发
【Azure Developer】在App Service上放置一个JS页面并引用msal.min.js成功获取AAD用户名示例
【Azure Developer】在App Service上放置一个JS页面并引用msal.min.js成功获取AAD用户名示例
141 1
|
前端开发 JavaScript 安全
JavaScript进阶-JavaScript库与框架简介
【7月更文挑战第11天】JavaScript库和框架加速Web开发,但也带来挑战。选择适合项目、团队技能的库或框架,如React、Angular、Vue,是关键。保持依赖更新,注意性能优化,避免过度依赖。遵循最佳实践,确保安全性,如防XSS和CSRF。学习基础,结合代码示例(如React计数器组件),提升开发效率和应用质量。
162 1
|
缓存 JavaScript 前端开发
JavaScript进阶 - Web Workers与Service Worker
【7月更文挑战第4天】JavaScript的Web Workers和Service Worker增强了Web性能。Web Workers处理后台多线程,减轻主线程负担,但通信有开销,受同源策略限制。Service Worker则用于离线缓存和推送通知,需管理其生命周期、更新策略,并确保安全。两者都带来了挑战,但也极大提升了用户体验。通过理解和优化,开发者能构建更高效、安全的Web应用。
314 2
|
资源调度 JavaScript 前端开发
JavaScript进阶 - JavaScript库与框架简介
【7月更文挑战第5天】JavaScript库和框架构成了前端开发的核心,如jQuery简化DOM操作,Angular、React和Vue提供全面解决方案。选择时要明确需求,避免过度工程化和陡峭学习曲线。使用版本管理工具确保兼容性,持续学习以适应技术变化。示例展示了jQuery和React的简单应用。正确选择和使用这些工具,能提升开发效率并创造优秀Web应用。
139 2
|
存储 移动开发 JavaScript
JavaScript简介及示例
JavaScript简介及示例

热门文章

最新文章