Javascript 了解 Service Worker 范围

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35780397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:12:21  来源:igfitidea点击:

Understanding Service Worker scope

javascriptscopeservice-worker

提问by Brian Leach

I am trying to implement a Service Workerin a test page. My end goal is an application that operates offline. The folder structure is below

我正在尝试Service Worker在测试页面中实现一个。我的最终目标是一个离线运行的应用程序。文件夹结构如下

/myApp
  ...
  /static
    /mod
      /practice
        service-worker.js
        worker-directives.js
        foopage.js
  /templates
    /practice
      foopage.html

I am registering a service worker as shown below (within service-worker.js):

我正在注册一个服务工作者,如下所示(在 内service-worker.js):

navigator.serviceWorker.register('../static/mod/practice/service-worker.js').then(function(reg) {
    console.log('Registration succeeded. Scope is ' + reg.scope);
    ...
}

and in the console I see

在控制台中我看到

Registration succeeded. Scope is https://example.com/static/mod/practice/

Registration succeeded. Scope is https://example.com/static/mod/practice/

If my page is located at https://example.com/practice/foopage, do I need to make sure that my service workerscope is https://example.com/practice/foopage?

如果我的页面位于https://example.com/practice/foopage,我是否需要确保我的service worker范围是https://example.com/practice/foopage

If I try to define the scope in the registerfunction call like

如果我尝试在register函数调用中定义范围,例如

navigator.serviceWorker.register('../static/mod/practice/service-worker.js', { scope: '/practice/foopage/' }).then(function(reg) {
    ...
}

I get the error

我收到错误

Registration failed with SecurityError: Failed to register a ServiceWorker: The path of the provided scope ('/practice/foopage/') is not under the max scope allowed ('/static/mod/practice/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.

Question is:What exactly does scoperefer to? Is it the collection of URLs that the service workerwill eventually control? Do I need to move service-workers.jssomewhere else? If so, where?

问题是:范围究竟指的是什么?它是service worker最终控制的 URL 集合吗?我需要搬到service-workers.js别的地方吗?如果有,在哪里?

回答by nils

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

Service Worker 基本上是您的 Web 应用程序和 Internet 之间的代理,因此如果需要,它可以拦截对网络的调用。

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

此实例中的范围是指 Service Worker 将能够拦截来自其的网络调用的路径。scope可以使用该属性明确定义它将涵盖的范围。然而:

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:

Service Worker 只能拦截源自 Service Worker 脚本所在的当前目录及其子目录范围内的请求。或者如 MDN 所述

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.

Service Worker 只会在 Service 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.

由于您的服务工作者位于/static/mod/practice/,因此不允许将其范围设置为/practice/foopage/。对其他主机的请求,例如https://stackoverflow.com/foo,在任何情况下都可以被拦截。

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).

确保您的 Service Worker 可以拦截它需要的所有调用的最简单方法是将它放在您的 Web 应用程序的根目录中 ( /)。您还可以使用 http 标头覆盖默认限制并手动设置范围(请参阅 Ashraf Sabry 的回答)。

回答by Ashraf Sabry

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

将 Service Worker 文件保留在您的项目结构强加的任何目录中,并将scope选项设置为/并将Service-Worker-AllowedHTTP 标头添加到您的 Service Worker 文件的响应中。

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

我正在使用 IIS,因此我会将以下内容添加到 web.config 文件中:

<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:

并通过以下方式注册工人:

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.

在 Firefox 和 Chrome 上测试。

Refer to the examples in Service worker specification

请参阅Service Worker 规范中的示例

回答by shriek

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

对于使用 nginx 的人来说,它再简单不过了:

# Given that /static is your route to assets
location /static {
        # using / as root scope
        add_header Service-Worker-Allowed /;
....