了解服务工作者范围

时间:2016-03-03 18:44:44

标签: javascript scope service-worker

我正在尝试在测试页面中实现Service Worker。我的最终目标是离线操作的应用程序。文件夹结构在

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

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

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

在控制台中我看到了

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

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

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

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

我收到错误

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.

问题是: 范围究竟是指什么?它是service worker最终将控制的URL集合吗?我是否需要在其他地方移动service-workers.js?如果是这样,在哪里?

3 个答案:

答案 0 :(得分:28)

服务工作者基本上是您的网络应用程序和互联网之间的代理,因此如果需要,它可以拦截对网络的呼叫。

此实例中的范围是指服务工作者能够拦截网络呼叫的路径。可以使用scope属性明确定义它将涵盖的范围。但是:

服务工作者只能拦截源自服务工作者脚本所在的当前目录范围内的请求及其子目录。 Or as MDN states

  

服务工作者只会在服务工作者的范围内捕获来自客户的请求。

     

服务工作者的最大范围是工作人员的位置。

由于您的服务工作人员位于/static/mod/practice/,因此不允许将其范围设置为/practice/foopage/。对其他主机的请求,例如https://stackoverflow.com/foo,无论如何都可以截获。

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

答案 1 :(得分:14)

将服务工作者文件保留在项目结构强加的任何目录中,并将scope选项设置为/,并将Service-Worker-Allowed HTTP标头添加到服务工作者文件的响应中。

我正在使用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>

通过以下方式注册工人:

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);
        });

在Firefox和Chrome上测试过。

请参阅Service worker specification

中的示例

答案 2 :(得分:0)

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

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