如何防止同一服务工作者注册多个页面?

时间:2015-11-19 23:33:38

标签: javascript service-worker

我有一个服务工作者脚本,它在多个站点级别上重复注册。

换句话说,同一服务人员已注册www.site.ca/,www.site.ca/text-text,www.site.ca/example-example等。

该网站建立在php上,根据内容生成不同的网址,因此类似API。服务工作者注册在这些页面上的原因是因为大多数站点流量落在这些页面而不是主页上。结果是同一服务工作者在不同页面上注册了不同的ID。

有没有人有办法阻止在多个子级别上多次注册同一个脚本?

编辑:

即使用户不在网站上,服务工作者的目的是设置通知。此外,我所遇到的问题会对将来更新服务工作者的任何尝试产生负面影响,因为会有多个副本需要更新。结果是当用户在特定页面上再次登陆站点时,只有一个副本会被更新。无法保证该服务工作文件的所有副本都将得到更新。此外,多个副本的结果导致用户从站点获得通知堆栈,因此这是一个问题。

编辑:

以下是我到目前为止的内容,我的理解范围定义了它的注册位置。然而问题是它需要能够在人进入网站的任何地方进行注册,因此范围被设置为' /'。

我想解决的问题是阻止同一服务工作文件的后续注册。

Localhost是实际网站的占位符。

navigator.serviceWorker.register('localhost/service-worker.js', {scope: './'})
.then(initialiseState);

在用于调试的Chrome开发工具中,生成的服务工作者的格式如下:

范围:localhost / url / stuff /
注册ID:110
积极的工作人员:
安装状态:激活
运行状态:停止了 脚本:localhost / service-worker.js
...

范围:localhost /
注册ID:111
积极的工作人员:
安装状态:激活
运行状态:停止了 脚本:localhost / service-worker.js
...

范围:localhost / url
注册ID:112
积极的工作人员:
安装状态:激活
运行状态:停止了 脚本:localhost / service-worker.js
......

理想情况下,我想以某种方式将它保存到一个条目。

2 个答案:

答案 0 :(得分:14)

在site-with-sub-directories场景中,您希望所有子页面都由同一顶级服务工作者控制,我建议使用绝对URL作为服务工作者脚本位置,并且然后依赖于省略options.scope时发生的默认行为。

请注意,其他响应中引用的MDN docs对于默认行为不正确。服务人员specificationupdated in January 2015,将默认范围更改为等同于new URL('./', serviceWorkerScriptUrl).toString()。 (MDN文档有since been updated,应该准确。)

为了说明为什么我建议在此用例中省略options.scope,请考虑以下备选方案,假设您需要单个共享服务工作者注册:

  • navigator.serviceWorker.register('/sw.js')会为您提供/范围内的注册,这是您想要的。
  • navigator.serviceWorker.register('/sw.js', {scope: '/'})会为您提供/范围内的注册,这也是您想要的,但与默认行为相比,它不会带来任何好处。
  • navigator.serviceWorker.register('/subsite/sw.js', {scope: '/'})将无法注册,因为/的范围对于位于/subsite/sw.js的服务工作者脚本而言过于宽泛。
  • navigator.serviceWorker.register('/subsite/sw.js')会为您提供/subsite范围内的注册,这是您想要的。
  • navigator.serviceWorker.register('/subsite/sw.js', {scope: '/subsite'})可行,但同样,它并没有为您提供超过默认行为的任何好处。

我建议明确设置options.scope的值的唯一情况是,您需要明确地将服务工作者的范围限制为比默认范围更窄。

请注意,如果您决定为options.scope提供值,并且该值是'./'之类的相对URL,则该URL将被解释为相对于脚本/页面调用的位置register(){scope: './'} 被解释为相对于服务工作者脚本URL的位置。有一段时间我对这一点感到困惑,所以花一些时间来充分理解那里的含义。这就解释了为什么你在最初的问题中最终会有多个注册。

答案 1 :(得分:12)

根据MDNServiceWorkerContainer.register方法采用了第二个选项参数:

  

目前可用的选项包括:

     
      
  • 范围:表示定义服务工作者注册范围的URL的USVString;服务工作者可以使用的URL范围   控制。这通常是相对网址,默认为' /'什么时候   未指定。
  •   

至于您的更新问题,W3C Service Workers WD说:

  

一个服务工作者注册相同范围的URL   已存在于用户代理中导致现有服务工作者   注册需要更换。

因此navigator.serviceWorker.register(url, {scope: '/'}).then(doSomething)应该有用。

问题在于示例中的范围网址:

./应为/