npm i
- установить зависимости.
npm start
- запустить сервер.
open http://localhost:3000/
- открыть приложение в браузере.
Описанная в задании последовательность действий позволяет выделить следующие требования к выполнению задания:
- Приложение должно работать в офлайн-режиме: загрузка главной страницы и просмотр избранного.
- Главная страница и статика из директорий vendor и assets должны браться из кэша только в офлайн-режиме.
Пройдемся снизу вверх по описанной в задании последовательности действий
ServiceWorker перестал обрабатывать запросы за ресурсами приложения: HTML-страницей, скриптами и стилями из каталогов vendor и assets. после рефакторинга «Разложить файлы красиво»
Проблема связана с тем, что Service Worker может работать с ресурсами
из своей области видимости - директории в которой он находится либо дочерними.
Для решения проблемы переместим service-worker.js
на уровень выше,
исправим пути для импорта в нем и в файле assets/blocks.js
.
Оказалось, что невозможно обновить статику из директорий vendor и assets. Но всё наладилось само собой после того, как был проведён рефакторинг под названием «Разложить файлы красиво»
Причина, по которой вероятнее всего статику было невозможно обновить, заключалась в следующем фрагменте кода:
// service-worker.js, тело обработчика 'fetch'
if (needStoreForOffline(cacheKey)) { // проверка на файлы статики
response = caches.match(cacheKey)
.then(cacheResponse => cacheResponse || fetchAndPutToCache(cacheKey, event.request));
} else {
Здесь видно, что для статики ServiceWorker всегда отдает ответ из кэша (за исключением первого запроса).
После рефакторинга «Разложить файлы красиво», как было сказано ранее, Service Worker не имел доступа к ресурсам, их кэширования не производилось, поэтому проблема и "исчезла". Другие описанные проблемы вероятно также связаны с этим участком кода.
Были предприняты следующие действия:
Убрано возвращение файлов из кэша для статики перед отправкой запроса на сервер.
Верная логика (возвращение файлов из кэша только в случае неудачного запроса) уже и так
реализована в fetchAndPutToCache
, которая для наглядности была переименована.
Была модифицирована функция needStoreForOffline
для
корректной работы с запросом главной страницы (возможно специфично для выбранной реализации сервера, тут не уверен)
Вопрос №1: зачем нужен этот вызов?
self.skipWaiting()
вinstall
.
Вопрос №2: зачем нужен этот вызов?
self.clients.claim()
вactivate
Чтобы убедиться, что обновление соответствующего сервис воркера возымело эффект сразу же как на текущего клиента, так и на всех других активных клинетов. [Clients.claim() - Интерфейсы веб API | MDN]
Вопрос №3: для всех ли случаев подойдёт такое построение ключа?
const cacheKey = url.origin + url.pathname
Нет, т.к. не учитывает url.search
.
Вопрос №4: Зачем нужна эта цепочка вызовов?
return Promise.all(
names.filter(name => name !== CACHE_VERSION)
.map(name => {
console.log('[ServiceWorker] Deleting obsolete cache:', name);
return caches.delete(name);
})
);
В Promise.all
передается массив промисов удаления неактуальных кэшей.
Этот массив получается из массива имен всех кэшей, которые не равны текущему CACHE_VERSION
(filter)
и преобразованного к массиву промисов удаления соответствующих кэшей (map).
В Promise.all
оборачиваем, чтобы иметь возможность сохранить последовательность
выполненния операций при асинхронных действиях. (Операция удаления кэша является асинхронной).
deleteObsoleteCaches.then(() => {
// код внутри этой функции гарантированно вызовется после удаления всех неактуальных кэшей
})
Вопрос №5: для чего нужно клонирование?
cache.put(cacheKey, response.clone());
response
является потоком и может быть прочитан только единожды.
В данном случае оригинальный объект отправится браузеру, а клон будет закеширован.
Оба они будут прочитаны единожды. [Восстановление неудачных запросов]