Автономный резерв для адаптивных изображений к наибольшему кэшированному изображению

#workbox

#workbox

Вопрос:

У меня есть проект, использующий srcset для изображений. Все они находятся в своих подкаталогах, похожих на:

  • /images/image1/100.jpg , 200.jpg , 500.jpg , 1000.jpg
  • /images/image2/100.jpg , 200.jpg , 500.jpg , 1000.jpg

Сайт использует изображения разного размера в списках и подробных представлениях. Например, переход от портретной к альбомной ориентации изменится с 100.jpg чтобы 200.jpg и для детального просмотра будет использоваться 500 или 1000.jpg в зависимости от размера видового экрана.

Возможно ли в автономном сценарии, чтобы workbox искал то, что кэшируется с помощью URI, начинающегося с «/images/image1/», и находил файл с наибольшим номером и возвращал его? Я бы предпочел использовать меньшее (или большее) изображение вместо поврежденного, если автономный пользователь меняется, например, с портретного на альбомный.

Ответ №1:

Конечно! Вот пользовательский плагин, который требует Workbox версии 6 и использует новое handlerDidError событие жизненного цикла для обеспечения резервного копирования:

 import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';

// Replace with your desired cache name.
const imagesCacheName = 'images-cache';

function parseImageNameAndSize(url) {
  const pattern = new RegExp('/([^/] )/(\d )\.jpg

(Я не тестировал весь этот код, но я думаю, что он должен быть близок к работе. Дайте мне знать, если у вас возникнут проблемы!)

Обратите внимание, что этот плагин "включится" только в том случае, если исходный запрос URL не может быть удовлетворен данной стратегией, скорее всего, потому, что вы находитесь в автономном режиме и совпадение кэша отсутствует. Если вы хотите настроить Workbox так, чтобы он всегда использовал изображение самого высокого качества, когда оно было доступно в кэше, даже когда вы подключены к Сети или когда есть совпадение кэша для изображения более низкого качества, это можно сделать (потенциально в  cachedResponseWillBeUsed  обратном вызове). Но я думаю, что для конкретного случая использования, который вы описываете, использование нового  handlerDidError  обратного вызова - лучший подход.


Комментарии:

1. Он отлично работает - и был подключи и играй. Миллион благодарностей, Джефф! Это была самая большая проблема, с которой я столкнулся, чтобы заставить этот проект хорошо работать в автономном режиме, поэтому теперь я пойду по кроличьей норе и посмотрю, смогу ли я заставить его всегда использовать кеш, если более высокие разрешения уже кэшированы.

);
const [_, name, size] = pattern.exec(url) || [];

// This will return [undefined, NaN] when there's no match.
return [name, parseInt(size)];
}

async imageFallback({error, request}) {
let largestSize = -1;
let cacheKeyOfLargestImage;

const [originalName, _] = parseImageNameAndSize(request.url);
// If the URL doesn't match our RegExp, re-throw the underlying error.
if (!originalName) {
throw error;
}

const cache = await caches.open(imagesCacheName);
const cachedRequests = await cache.keys();
// Iterate through all of the cache entries to find matches:
for (const cachedRequest of cachedRequests) {
const [name, size] = parseImageNameAndSize(cachedRequest.url);
if ((name === originalName) amp;amp; (size > largestSize)) {
largestSize = size;
cacheKeyOfLargestImage = cachedRequest;
}
}

if (cacheKeyOfLargestImage) {
// If we have the cache key for the largest image that meets
// the conditions, return the cached response.
return cache.match(cacheKeyOfLargestImage);
}

// If there is no image the cache that satisfies these conditions,
// re-throw the underlying error.
throw error;
}

// Now, use the callback as a plugin by associating it with
// handerDidError in the strategy of your choice
// (CacheFirst, StaleWhileRevalidate, etc.):
registerRoute(
// Match any request whose path ends in .jpg
({url}) => url.pathname.endsWith('.jpg'),
new CacheFirst({
cacheName: imagesCacheName,
plugins: [
{handlerDidError: imageFallback},
// Add any other plugins you want.
],
})
);
(Я не тестировал весь этот код, но я думаю, что он должен быть близок к работе. Дайте мне знать, если у вас возникнут проблемы!)

Обратите внимание, что этот плагин «включится» только в том случае, если исходный запрос URL не может быть удовлетворен данной стратегией, скорее всего, потому, что вы находитесь в автономном режиме и совпадение кэша отсутствует. Если вы хотите настроить Workbox так, чтобы он всегда использовал изображение самого высокого качества, когда оно было доступно в кэше, даже когда вы подключены к Сети или когда есть совпадение кэша для изображения более низкого качества, это можно сделать (потенциально в cachedResponseWillBeUsed обратном вызове). Но я думаю, что для конкретного случая использования, который вы описываете, использование нового handlerDidError обратного вызова — лучший подход.

Комментарии:

1. Он отлично работает — и был подключи и играй. Миллион благодарностей, Джефф! Это была самая большая проблема, с которой я столкнулся, чтобы заставить этот проект хорошо работать в автономном режиме, поэтому теперь я пойду по кроличьей норе и посмотрю, смогу ли я заставить его всегда использовать кеш, если более высокие разрешения уже кэшированы.