#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. Он отлично работает — и был подключи и играй. Миллион благодарностей, Джефф! Это была самая большая проблема, с которой я столкнулся, чтобы заставить этот проект хорошо работать в автономном режиме, поэтому теперь я пойду по кроличьей норе и посмотрю, смогу ли я заставить его всегда использовать кеш, если более высокие разрешения уже кэшированы.