乐闻世界logo
搜索文章和话题

How to understanding service worker scope?

8 个月前提问
5 个月前修改
浏览次数149

5个答案

1
2
3
4
5

Service Worker 的作用域(Scope)定义了它能够控制的内容范围,即 Service Worker 可以拦截和处理哪些请求。作用域是通过 Service Worker 注册时指定的,一般来说,Service Worker 只能控制其注册所在路径和下级路径的请求。

例如,如果您在 /app/ 路径下注册了一个 Service Worker,它的作用域将被限制在 /app/ 及其子路径下。这意味着,Service Worker 可以拦截 /app//app/home/app/settings 等路径的请求,但它无法控制 / 根路径或 /other 路径下的请求。

这个作用域的限定有助于确保 Service Worker 不会影响到其它不相关的页面和应用,提供了一种安全的方式来限制 Service Worker 的控制范围。

举个例子,如果一个在线商城网站在其根目录下注册了 Service Worker,并设置了根目录为作用域,那么这个 Service Worker 将能控制商城网站的所有页面。然而,如果商城网站希望仅仅对产品目录页面使用 Service Worker 来缓存和提供离线支持,那么它可以单独在 /products/ 路径下注册一个 Service Worker,将作用域限制在这个子目录中。这样,Service Worker 只会影响 /products/ 路径下的请求,而不会影响到其他页面。

2024年6月29日 12:07 回复

Service workers are basically a proxy between your web application and the internet, so it can intercept calls to the network if so desired.

Scope in this instance refers to the path that the service worker will be able to intercept network calls from. The scope property can be used explicitly define the scope it will cover. However:

Service workers can only intercept requests originating in the scope of the current directory that the service worker script is located in and its subdirectories. Or as MDN states:

The service worker will only catch requests from clients under the service worker's scope.

The max scope for a service worker is the location of the worker.

As your service worker is located in /static/mod/practice/, it's not allowed to set its scope to /practice/foopage/. Requests to other hosts, e.g. https://stackoverflow.com/foo, can be intercepted in any case.

The easiest way to ensure that your service worker can intercept all the calls it needs to, would be to place it in the root directory of your web app (/). You can also override the default restrictions using an http header and manually setting the scope (see Ashraf Sabry's answer).

2024年6月29日 12:07 回复

Leave the service worker file in whatever directory imposed by your project structure and set the scope option to / and add the Service-Worker-Allowed HTTP header to the response of your service worker file.

I'm using IIS, so I would add the following to web.config file:

shell
<location path="static/mod/practice/service-worker.js"> <system.webServer> <httpProtocol> <customHeaders> <add name="Service-Worker-Allowed" value="/" /> </customHeaders> </httpProtocol> </system.webServer> </location>

And register the worker by:

shell
navigator.serviceWorker.register('/static/mod/practice/service-worker.js', { scope: '/' }) .then(function (registration) { console.log('Service worker registered successfully'); }).catch(function (e) { console.error('Error during service worker registration:', e); });

Tested on Firefox and Chrome.

Refer to the examples in Service worker specification

2024年6月29日 12:07 回复

For the people who are using nginx it couldn't be any simpler:

shell
# Given that /static is your route to assets location /static { # using / as root scope add_header Service-Worker-Allowed /; ....
2024年6月29日 12:07 回复

Just in case if the scope changes between development & production environment, as often we use local subdirectories for projects, using "./" for the scope may save the day (& make it dynamic).

shell
navigator.serviceWorker.register( `./service-worker.js`, { scope: `./` } );
2024年6月29日 12:07 回复

你的答案