了解 Service Worker 范围

IT技术 javascript scope service-worker
2021-01-12 10:39:08

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

/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个回答

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

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

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

Service Worker 只会在 Service Worker 的范围内捕获来自客户端的请求。

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

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

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

我不认为js根目录中文件是可以完成的。但随着新概念的出现,我想新的范式
2021-03-19 10:39:08
这只是部分正确——范围决定了哪些页面是由 Service Worker 控制的。一旦页面被 Service Worker 控制,所有源自该页面的 HTTP 请求,无论请求 URL 是什么,都将触发 Service Worker 的fetch事件。因此,如果受控页面对 发出 AJAX 请求https://thirdpartyapi.com/api/test,您的服务工作者将有机会拦截该请求
2021-03-30 10:39:08
我认为这主要是出于安全原因。例如,如果您只能访问/static,而不能访问根 ( /),则您的服务工作者应该无法拦截对根的请求。
2021-04-10 10:39:08

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

我正在使用 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 规范中的示例

我被设置为 Service-Worker-Allowed 的 http 响应:/ 但它仍然对我不起作用。它注册 SW 并在 1 秒后自动取消注册该服务工作者。你能看看demo3.icubes.org
2021-03-24 10:39:08

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

# Given that /static is your route to assets
location /static {
        # using / as root scope
        add_header Service-Worker-Allowed /;
....
我的服务人员没有注册。我认为问题出在范围上。我尝试了您的解决方案,现在 Service Worker 注册成功。谢谢!
2021-03-24 10:39:08