Могу ли я отредактировать кешированный index.html перед тем, как служить в сервис-воркере?

Разрабатываемое мной веб-приложение открывается в веб-просмотре по почте. Параметры тела сообщения (контекстные данные, вводимые пользователем) вставляются в index.html.

Таким образом, повторные загрузки не работают из-за отсутствия контекстного ввода.

В официальных документах говорится, что с этим ничего не поделать. В нем говорится, что все, что вы можете сделать сейчас, это сначала подключиться к сети и включить предварительную загрузку навигации. (https://developers.google.com/web/tools/workbox/modules/workbox-navigation-preload --------- «Эта функция предназначена для уменьшения задержки навигации для разработчиков, которые не могут предварительно кэшировать свой HTML ...»)

Следовательно, я ищу способ отредактировать мой кешированный index.html до того, как он будет использован. Я хочу вставить параметры тела сообщения в index.html. Я не могу найти документацию по редактированию кеша. Следовательно, любая помощь / вклад сообщества будут оценены.


person Ashrith    schedule 13.08.2019    source источник


Ответы (1)


Workbox! == сервис воркер. Workbox построен поверх сервис-воркера, но необработанные сервис-воркеры дают вам полный контроль над запросом и ответом, поэтому вы можете делать практически все, что захотите.

Редактирование ответа

Вот как вы можете изменить текст ответа:

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);
  }());
});

Здесь есть потенциальная проблема с производительностью, заключающаяся в том, что вы в конечном итоге загружаете полный ответ в память и выполняете работу по замене до того, как обслуживаете первый байт. Приложив немного больше усилий, вы можете выполнить замену в потоковом режиме:

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);
  })());
});

Вот живая демонстрация вышеуказанного.

Получение 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'));
  }());
});

См. страницу MDN для FormData API.

person JaffaTheCake    schedule 13.08.2019
comment
Отличный ответ, я хотел поиграть с этим! Примечание: демонстрация, к сожалению, в моем случае показалась сломанной, поскольку Firefox, похоже, не поддерживает TransformStream (пока), в то время как Chromium и недавний Safari ›= 14.1 работают. Как указано на связанной демонстрационной странице, я пока протестирую поддержку потоков и вернусь к другому методу, если такой поддержки нет. - person Jason; 03.05.2021