在 Service Worker 中服务之前,我可以编辑缓存的 index.html 吗?

Ash*_*ith 2 service-worker progressive-web-apps workbox

我正在开发的 webapp 通过 post 在 webview 中打开。帖子正文参数(上下文用户输入)被插入到 index.html 中。

所以重复加载失败,因为上下文输入不存在。

官方文档说对此无能为力。它说你现在所能做的就是先进入网络并启用导航预加载。(https://developers.google.com/web/tools/workbox/modules/workbox-navigation-preload --------- “此功能旨在为无法预缓存其的开发人员减少导航延迟HTML……”)

因此,我正在寻找一种在使用之前编辑我缓存的 index.html 的方法。我想将帖子正文参数插入到 index.html 中。我找不到有关编辑缓存的任何文档。因此,来自社区的任何帮助/投入将不胜感激。

Jaf*_*ake 5

工作箱!== 服务工作者。Workbox 建立在 Service Worker 之上,但原始 Service Worker 让您可以完全控制请求和响应,因此您几乎可以做任何想做的事情。

编辑回复

以下是更改回复文本的方法:

addEventListener('fetch', event => {
  event.respondWith(async function() {
    // Get a cached response:
    const cachedResponse = await caches.match('/');
    // Get the text of the response:
    const responseText = await cachedResponse.text();
    // Change it:
    const newText = responseText.replace(/Hello/g, 'Goodbye');
    // Serve it:
    return new Response(newText, cachedResponse);
  }());
});
Run Code Online (Sandbox Code Playgroud)

这里有一个潜在的性能问题,您最终将完整的响应加载到内存中,并在提供第一个字节之前进行替换工作。只需稍加努力,您就可以以流式方式进行替换:

function streamingReplace(find, replace) {
  let buffer = '';

  return new TransformStream({
    transform(chunk, controller) {
      buffer += chunk;
      let outChunk = '';

      while (true) {
        const index = buffer.indexOf(find);
        if (index === -1) break;
        outChunk += buffer.slice(0, index) + replace;
        buffer = buffer.slice(index + find.length);
      }

      outChunk += buffer.slice(0, -(find.length - 1));
      buffer = buffer.slice(-(find.length - 1));
      controller.enqueue(outChunk);
    },
    flush(controller) {
      if (buffer) controller.enqueue(buffer);
    }
  })
}

addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if (!(url.origin === location.origin && url.pathname === '/sw-content-change/')) return;

  event.respondWith((async function() {
    const response = await fetch(event.request);
    const bodyStream = response.body
      .pipeThrough(new TextDecoderStream())
      .pipeThrough(streamingReplace('Hello', 'Goodbye'))
      .pipeThrough(new TextEncoderStream());

    return new Response(bodyStream, response);
  })());
});
Run Code Online (Sandbox Code Playgroud)

这是上面的现场演示

获取响应的 POST 参数

您需要的另一部分是获取响应的 POST 正文:

addEventListener('fetch', event => {
  event.respondWith(async function() {
    if (event.request.method !== 'POST') return;

    const formData = await event.request.formData();
    // Do whatever you want with the form data…
    console.log(formData.get('foo'));
  }());
});
Run Code Online (Sandbox Code Playgroud)

有关API 的信息,请参阅MDN 页面FormData