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

KRO*_*Orb 14 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);
Run Code Online (Sandbox Code Playgroud)

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

范围:localhost/url/stuff/
注册ID:110
活动工作者:
安装状态:ACTIVATED
运行状态:STOPPED
脚本:localhost/service-worker.js
...

范围:localhost/
注册ID:111
活动工作者:
安装状态:ACTIVATED
运行状态:STOPPED
脚本:localhost/service-worker.js
...

范围:localhost/url
注册ID:112
活动工作者:
安装状态:ACTIVATED
运行状态:STOPPED
脚本:localhost/service-worker.js
...

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

Jef*_*ick 16

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

请注意,其他响应中引用的MDN文档对于默认行为是不正确的.服务工作者规范已于2015年1月更新,以将默认范围更改为等效new URL('./', serviceWorkerScriptUrl).toString().(MDN文档已经更新,应该准确.)

为了说明为什么我建议省略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的位置.有一段时间我对这一点感到困惑,所以花一些时间来充分理解那里的含义.这就解释了为什么您在最初的问题中最终会进行多次注册.

  • 我修复了MDN页面. (2认同)

Rūd*_*nis 14

根据MDN,ServiceWorkerContainer.register方法采用第二个选项参数:

目前可用的选项包括:

  • scope:USVString,表示定义服务工作者注册范围的URL; 服务工作者可以控制的URL范围.这通常是相对URL,未指定时默认为"/".

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

当用户代理中已存在相同范围URL的服务工作者注册时,将导致替换现有服务工作者注册.

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

问题在于示例中的范围URL:

./ 应该 /

  • 服务工作者 - 就像appcache一样 - 应该链接到应用程序的所有页面并注册.实际上,上面的问题是你指定一个*relative*scope(`./`),它强制创建新的服务工作者实例,而不管服务工作者脚本本身是否相同.如果要将相同的实例附加到所有页面,无论路径如何,都应该使用绝对/根路径,例如`/`作为范围. (2认同)