Mapbox GL JS опирается на многоуровневую систему загрузки и хранения данных, где ключевую роль играет кэширование ресурсов карты: тайлов, стилей, шрифтов (glyphs), спрайтов и метаданных источников. Cache API в браузере становится основным инструментом для контроля сетевых запросов и обеспечения офлайн-доступа, ускорения повторной отрисовки и снижения нагрузки на серверы картографического провайдера.
При рендеринге карты Mapbox GL JS формирует множество параллельных запросов к внешним ресурсам:
Каждый слой карты может инициировать собственные запросы, и именно здесь кэширование становится критическим элементом производительности.
Mapbox предоставляет CDN-инфраструктуру, однако на стороне клиента браузерный Cache API позволяет перехватывать и повторно использовать уже загруженные данные без повторных обращений к сети.
Cache API — это интерфейс Web Platform, предназначенный для хранения HTTP-ответов в виде пар request/response. В контексте Mapbox GL JS он используется через Service Worker или промежуточные прокси-слои.
Основные особенности:
Cache API не является автоматическим кэшем Mapbox GL JS — он подключается разработчиком при необходимости контроля сетевого поведения.
Тайлы являются наиболее частыми и тяжёлыми запросами в Mapbox GL JS. Они делятся на:
.pbf).png, .jpg,
.webp)Типичный URL тайла содержит координаты {z}/{x}/{y} и
параметры стиля.
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
if (url.pathname.includes('/tiles/')) {
event.respondWith(
caches.open('map-tiles-v1').then(async (cache) => {
const cached = await cache.match(event.request);
if (cached) return cached;
const response = await fetch(event.request);
cache.put(event.request, response.clone());
return response;
})
);
}
});
В этом сценарии:
Стиль карты (style.json) определяет:
Эти ресурсы менее динамичны и идеально подходят для долгоживущего кэша.
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('style.json')) {
event.respondWith(
caches.match(event.request).then((cached) => {
if (cached) return cached;
return fetch(event.request).then((response) => {
return caches.open('map-styles-v1').then((cache) => {
cache.put(event.request, response.clone());
return response;
});
});
})
);
}
});
Glyphs (шрифты) и sprites часто представляют собой множественные мелкие запросы, чувствительные к задержкам сети.
Особенности кэширования:
/{fontstack}/{range}.pbf)Оптимизация достигается через:
Полноценная офлайн-работа Mapbox GL JS строится поверх Cache API и Service Worker.
async function preCacheTiles(tileUrls) {
const cache = await caches.open('offline-map-v1');
await Promise.all(
tileUrls.map(async (url) => {
const response = await fetch(url);
if (response.ok) {
await cache.put(url, response);
}
})
);
}
Service Worker выступает центральным контроллером кэширования.
Он позволяет:
self.addEventListener('fetch', (event) => {
event.respondWith(
fetch(event.request)
.then((response) => {
const cloned = response.clone();
caches.open('dynamic-v1').then((cache) => {
cache.put(event.request, cloned);
});
return response;
})
.catch(() => caches.match(event.request))
);
});
Mapbox GL JS активно использует версии стилей и источников данных. Это критично для предотвращения конфликтов старых и новых данных.
Практика:
const CACHE_VERSION = 'v3';
const CACHE_NAME = `mapbox-cache-${CACHE_VERSION}`;
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(
keys
.filter((key) => key !== CACHE_NAME)
.map((key) => caches.delete(key))
)
)
);
});
Эффективное использование Cache API напрямую влияет на:
Ключевые принципы:
Несмотря на гибкость, Cache API имеет ограничения:
В результате требуется дополнительный слой управления кэшем:
На практике Mapbox GL JS приложения используют комбинированные модели:
Такая комбинация обеспечивает баланс между актуальностью данных и производительностью рендеринга.
Кэширование влияет на внутренний pipeline рендера:
При правильно настроенном Cache API: