在安装前将状态信息传递给服务人员 [英] Passing state info into a service worker before `install`

查看:24
本文介绍了在安装前将状态信息传递给服务人员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我是服务人员的新手,但是正在使用图书馆,该图书馆旨在成为离线-首先"(实际上,几乎是仅离线")(FWIW),目的是允许库的使用者提供表示表格多线性文本的JSON配置,并返回一个允许其用户以高度可定制的方式浏览这些文本的应用程序方式按段落/段落范围进行.)

其他项目是将库安装为依赖项,然后通过我们的JavaScript API提供信息,例如JSON配置文件的路径,该路径指示我们的应用程序将使用这些文件来生成(离线)应用程序.

虽然我知道我们可以执行以下任何操作:

  1. 要求用户提供一个硬编码的路径,我们的服务人员的 install 脚本可通过该路径使用 waitUntil 及其自己的JSON请求来检索用户的必要文件
  2. 跳过服务工作者的JSON文件的服务工作者的 install 步骤,并依靠 fetch 事件更新缓存,如果用户已完成,则提供备用显示安装并在发生提取之前脱机.
  3. 将一些状态信息从我们的主脚本发布到服务器,服务工作者一旦注册,将在完成其 install 事件之前对其进行查询.

...但是所有选择似乎都不理想,因为分别是:

  1. 我们图书馆的消费者可能更愿意为自己的JSON配置指定自己的位置.
  2. 鉴于JSON配置指定了关键文件,这些文件对于向用户显示有用的内容至关重要,所以我宁愿不允许安装完成也只是说用户必须重新上网才能获得其余文件(如果没有使用该文件的话)能够在 install 事件发生后保持在线状态,以查看所有必需的提取操作.
  3. 除了希望避免更多的服务器访问和额外的代码外,我更希望我们的代码面向离线,以便能够完全在静态文件服务器上工作.

问题:

是否有某种方法可以将消息或状态信息传递给服务人员在发生 install 事件之前,是否作为服务人员URL的查询字符串的一部分,还是通过消息传递事件?只要在 install 中的 waitUntil 完成之前,该消息事件甚至可以在 install 事件开始后从技术上到达.

我知道我可以自己测试一下,但是我想知道当必须像我们这样的库中那样动态地获取关键应用程序文件时,最佳实践可能仍然是什么.

我猜这里 indexedDB 可能是唯一的选择(即,将配置信息或JSON配置的路径保存到indexedDB,注册服务工作者,并从 install 事件)?即使这样也不是很理想,因为我让用户为其存储定义了一个名称空间,但是我也需要一种将其传递给工作程序的方法,否则,原点上的多个此类应用程序可能会发生冲突.

解决方案

使用查询参数

如果您认为它有用,那么可以,可以在安装Service Worker时通过在注册时向Service Worker包含查询参数来提供状态,例如:

 //在您的主页内:const pathToJson ='/path/to/file.json';const swUrl ='/sw.js?pathToJson='+ encodeURIComponent(pathToJson);navigator.serviceWorker.register(swUrl);//在sw.js内部:self.addEventListener('install',event => {const pathToJson =新的URL(位置).searchParams.get('pathToJson');event.waitUntil(提取(pathToJson).then(response => response.json()).then(jsonData =>/*使用jsonData */));}); 

关于此方法的一些注意事项:

  • 如果您在 install 处理程序中(如代码示例中) fetch() JSON文件,则每个服务版本都会有效地发生一次工作脚本( sw.js ).如果JSON文件的内容发生更改,但其他所有内容保持不变,则服务工作者将不会自动检测到该情况并重新填充您的缓存.

  • 从第一点开始,如果您通过以下方法解决此问题,例如在JSON文件的URL中包含基于哈希的版本控制,则每次更改该URL时,最终都会安装一个新的Service Worker.从本质上来说,这并不是一件坏事,但是如果您的Web应用程序中有侦听服务人员生命周期事件的逻辑,则需要牢记这一点.

替代方法

您还可能会发现,从主页的上下文中仅将文件添加到缓存中会更容易,因为支持Cache Storage API的浏览器会通过 window.caches 公开该文件.不过,在服务工作者的 install 处理程序中预先缓存文件确实具有确保在安装服务工作者之前已成功缓存所有文件的优点.

另一种方法是从 window 上下文中将状态信息写入IndexedDB,然后在服务工作者的 install 处理程序中从IndexedDB读取.

Background

I'm new to service workers but working on a library that is intended to become "offline-first" (really, almost "offline-only") (FWIW, the intent is to allow consumers of the library to provide JSON config representing tabular multilinear texts and get in return an app which allows their users to browse these texts in a highly customizable manner by paragraph/verse ranges.)

Other projects are to install the library as a dependency and then supply information via our JavaScript API such as the path of a JSON config file indicating the files that our app will consume to produce an (offline) app for them.

While I know we could do any of the following:

  1. require users provide a hard-coded path from which our service worker's install script could use waitUntil with its own JSON request to retrieve the user's necessary files
  2. skip the service worker's install step of the service worker for the JSON file, and rely on fetch events to update the cache, providing a fallback display if the user completed the install and went offline before the fetches could occur.
  3. Post some state info from our main script to a server which the service worker, once registered, would query before completing its install event.

...but all choices seems less than ideal because, respectively:

  1. Our library's consumers may prefer to be able to designate their own location for their JSON config.
  2. Given that the JSON config designates files critical to showing their users anything useful, I'd rather not allow an install to complete only to say that the user has to go back online to get the rest of the files if they were not able to remain online after the install event to see all the required fetches occur.
  3. Besides wanting to avoid more trips to the server and extra code, I'd prefer for our code to be so offline-oriented as to be able to work entirely on mere static file servers.

Question:

Is there some way to pass a message or state information into a service worker before the install event occurs, whether as part of the query string of the service worker URL, or through a messaging event? The messaging event could even technically arrive after the install event begins as long as it can occur before a waitUntil within the install is complete.

I know I could test this myself, but I'd like to know what best practices might be anyways when the critical app files must themselves be dynamically obtained as in such libraries as ours.

I'm guessing indexedDB might be the sole alternative here (i.e., saving the config info or path of the JSON config to indexedDB, registering a service worker, and retrieving the indexedDB data from within the install event)? Even this would not be ideal as I'm letting users define a namespace for their storage, but I need a way for it too to be passed into the worker, or otherwise, multiple such apps on the origin could clash.

解决方案

Using a Query Parameter

If you find it useful, then yes, you can provide state during service worker installation by including a query parameter to your service worker when you register it, like so:

// Inside your main page:
const pathToJson = '/path/to/file.json';
const swUrl = '/sw.js?pathToJson=' + encodeURIComponent(pathToJson);
navigator.serviceWorker.register(swUrl);

// Inside your sw.js:
self.addEventListener('install', event => {
  const pathToJson = new URL(location).searchParams.get('pathToJson');
  event.waitUntil(
    fetch(pathToJson)
      .then(response => response.json())
      .then(jsonData => /* Do something with jsonData */)
  );
});

A few things to note about this approach:

  • If you fetch() the JSON file in your install handler (as in the code sample), that will effectively happen once per version of your service worker script (sw.js). If the contents of the JSON file change, but everything else stays the same, the service worker won't automatically detect that and repopulate your caches.

  • Following from the first point, if you work around that by, e.g., including hash-based versioning in your JSON file's URL, each time you change that URL, you'll end up installing a new service worker. This isn't a bad thing, per se, but you need to keep it in mind if you have logic in your web app that listens for service worker lifecycle events.

Alternative Approaches

You also might find it easier to just add files to your caches from within the context of your main page, since browsers that support the Cache Storage API expose it via window.caches. Precaching the files within the install handler of a service worker does have the advantage of ensuring that all the files have been cached successfully before the service worker installs, though.

Another approach is to write the state information to IndexedDB from the window context, and then read from IndexedDB inside of your service worker's install handler.

这篇关于在安装前将状态信息传递给服务人员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆