了解服务工作者范围

Bri*_*ach 32 javascript scope service-worker

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

/myApp
  ...
  /static
    /mod
      /practice
        service-worker.js
        worker-directives.js
        foopage.js
  /templates
    /practice
      foopage.html
Run Code Online (Sandbox Code Playgroud)

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

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

在控制台中,我看到了

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) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

我收到了错误

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.
Run Code Online (Sandbox Code Playgroud)

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

nil*_*ils 37

服务工作者基本上是您的Web应用程序和Internet之间的代理,因此如果需要,它可以拦截对网络的调用.

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

服务工作者只能拦截源自服务工作者脚本所在的当前目录范围内的请求及其子目录.或者作为MDN声明:

服务工作者将仅捕获服务工作者范围内的客户端请求.

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

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

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

  • 这只是部分正确 - 范围确定服务工作者控制哪些页面.一旦页面由服务工作者控制,*来自页面的所有*HTTP请求,无论请求URL如何,都将触发服务工作者的`fetch`事件.因此,如果受控页面对"https:// thirdpartyapi.com/api/test"发出AJAX请求,您的服务工作者将有机会拦截该页面. (14认同)
  • 我不认为根目录中的`js`文件是可以完成的.但我认为新概念出现了新的范例 (4认同)
  • 我认为这主要是出于安全考虑.如果您只能访问`/ static`,但不能访问root(`/`),那么您的服务工作者就不能拦截对根的请求. (3认同)

Ash*_*bry 26

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

我正在使用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>
Run Code Online (Sandbox Code Playgroud)

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

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);
        });
Run Code Online (Sandbox Code Playgroud)

在Firefox和Chrome上测试过.

请参阅服务工作者规范中的示例


shr*_*iek 14

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

# Given that /static is your route to assets
location /static {
        # using / as root scope
        add_header Service-Worker-Allowed /;
....
Run Code Online (Sandbox Code Playgroud)