К основному содержанию
скилл CX Codex

mapbox-web-performance-patterns — скилл для Claude Code: установка

Скилл учит ИИ-агента оптимизировать приложения на Mapbox GL JS: убирать каскадные задержки данных, уменьшать бандл стилей и переводить маркеры на GPU-слои.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add mapbox/mapbox-agent-skills --skill mapbox-web-performance-patterns -a claude-code
Открыть на GitHub

Что делает mapbox-web-performance-patterns

Скилл добавляет в контекст правила ускорения карт Mapbox GL JS, расставленные по силе влияния на интерфейс. На критическом уровне он требует устранять водопады инициализации. Вместо ожидания события загрузки карты данные запрашиваются параллельно через fetch. Точные параметры center и zoom задаются на старте сразу, чтобы исключить загрузку лишних тайлов до перехода в рабочую область.

Вторая проблема — раздутые сборки. Встраивание сырого JSON со стилями добавляет сотни килобайтов в JS, поэтому скилл переводит проект на внешние или хостинговые стили Mapbox. Для маркеров заданы конкретные пороги: обычные HTML-элементы допустимы только до 100 штук, а для объёмов от 100 до 10 000 точек агент перепишет код на GeoJSON-слои symbol.

Перенос точек с DOM-маркеров на слои symbol ломает индивидуальные слушатели событий на элементах: клики придётся обрабатывать через единый вызов map.on('click', layerId). Вторичные тяжёлые слои вроде 3D-рельефа или зданий откладываются через requestIdleCallback.

Какие задачи решает

  • устранить каскадную задержку при последовательной загрузке карты и GeoJSON
  • уменьшить стартовый бандл за счёт выноса стилей карты из кода
  • заменить медленные DOM-маркеры на GPU-слои symbol
  • настроить отложенный рендеринг 3D-зданий и рельефа через requestIdleCallback

Примеры запросов агенту

  • Проверь инициализацию Mapbox в initMap: есть ли тут каскадное ожидание данных?
  • Оптимизируй отрисовку 5000 точек на карте, чтобы убрать просадки кадров при зуме.
  • Как вынести тяжёлый JSON стиля карты из бандла сборщика?

Как установить mapbox-web-performance-patterns

1Через Skills CLI (Vercel)

npx skills add mapbox/mapbox-agent-skills --skill mapbox-web-performance-patterns -a claude-code

2Вручную: положить файлы

~/.claude/skills/mapbox-web-performance-patterns/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/mapbox-web-performance-patterns/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора18

mapbox-web-integration-patterns Официальные паттерны встраивания Mapbox GL JS в React, Vue, Svelte, Angular и на чистом JavaScript. Пригодится, когда карта течёт по памяти или не инициализируется в нужном хуке. CX Codex +1 2 600установок mapbox-style-patterns Готовые наборы слоёв и стилей Mapbox для типовых карт: поиск заведений, недвижимость, маршруты, доставка. Пригодится, когда нужен проверенный стиль, а не подбор цветов с нуля. CX Codex +1 2 300установок mapbox-geospatial-operations Скилл помогает агенту выбрать между геометрическими расчётами Turf.js и маршрутными API Mapbox. Пригодится, когда в задаче есть расстояния, зоны или маршруты. CX Codex +1 2 200установок mapbox-cartography Скилл с правилами картографии: иерархия слоёв, палитры, типографика и порядок отрисовки для стилей Mapbox. Пригодится, когда агент собирает стиль карты. CX Codex +1 2 100установок mapbox-data-visualization-patterns Готовые шаблоны визуализации данных на картах Mapbox для Claude Code: картограммы, тепловые слои и 3D-модели. Пригодится при отрисовке статистики и плотности точек. CX Codex +1 2 100установок mapbox-style-quality Скилл проверяет стили Mapbox перед релизом: валидирует выражения и GeoJSON, считает контраст текста по WCAG, оптимизирует файл стиля. CX Codex +1 2 000установок mapbox-search-integration Проводит агента через весь цикл внедрения поиска Mapbox: от вопросов о задаче до готового кода с нужным API и параметрами. CX Codex +1 1 900установок mapbox-token-security Набор правил безопасности для токенов Mapbox: разграничение публичных и секретных ключей, ограничение по URL и защита от тихих падений карты. CX Codex +1 1 900установок

Похожие

optimize-web-animations MengTo Останавливает фоновую анимацию вне экрана и устраняет утечки памяти во фронтенде. Пригодится, когда страница с CSS, Canvas или WebGL нагружает процессор и тормозит скролл. CX Codex +1 1 700установок js-performance-patterns patterns.dev Набор паттернов микрооптимизации JavaScript для горячих путей. Помогает агенту устранять просадки скорости в циклах, обработчиках событий и операциях с DOM. CX Codex +1 687установок web-performance-optimization davila7 Скилл для Claude, который помогает разобрать, почему сайт грузится медленно, и по шагам убрать узкие места. 3 490установок performance-and-web-vitals dembrandt Скилл помогает находить и устранять проблемы с Core Web Vitals и аудитами Lighthouse. Он даёт правила для оптимизации LCP, CLS, INP, изображений, шрифтов и скриптов. CX Codex +1 975установок web-performance-audit aj-geddes Скилл разбирает скорость загрузки страниц, находит узкие места и подсказывает, что чинить. Пригодится после крупных правок или жалоб на медленную загрузку. CX Codex +1 543установок pixijs-performance pixijs Скилл для профилирования и ускорения PixiJS v8: FPS, draw calls, память GPU. Пригодится, когда приложение тормозит или течёт память. CX Codex +1 6 000установок

Рядом в теме «Фронтенд и UI»

Всё по теме «Фронтенд и UI» →

Вопросы о mapbox-web-performance-patterns

Как установить mapbox-web-performance-patterns в Claude Code?

Выполните команду npx skills add mapbox/mapbox-agent-skills --skill mapbox-web-performance-patterns -a claude-code в терминале проекта.

Что делает скилл mapbox-web-performance-patterns?

Он предоставляет агенту готовые шаблоны оптимизации Mapbox GL JS: параллельную выборку данных, сокращение веса стилей и кластеризацию точек.

Когда скилл требует отказаться от стандартных HTML-маркеров?

HTML-маркеры через класс Marker разрешены только при количестве до 100 штук. Если точек от 100 до 10 000, скилл переводит их на слой symbol, а при больших объёмах включает кластеризацию.

Исходный текст

SKILL.md · MIT
---
name: mapbox-web-performance-patterns
description: Performance optimization patterns for Mapbox GL JS web applications. Covers initialization waterfalls, bundle size, rendering performance, memory management, and web optimization. Prioritized by impact on user experience.
---

# Mapbox Performance Patterns Skill

This skill provides performance optimization guidance for building fast, efficient Mapbox applications. Patterns are prioritized by impact on user experience, starting with the most critical improvements.

**Performance philosophy:** These aren't micro-optimizations. They show up as waiting time, jank, and repeat costs that hit every user session.

## Priority Levels

Performance issues are prioritized by their impact on user experience:

- **🔴 Critical (Fix First)**: Directly causes slow initial load or visible jank
- **🟡 High Impact**: Noticeable delays or increased resource usage
- **🟢 Optimization**: Incremental improvements for polish

---

## 🔴 Critical: Eliminate Initialization Waterfalls

**Problem:** Sequential loading creates cascading delays where each resource waits for the previous one.

**Note:** Modern bundlers (Vite, Webpack, etc.) and ESM dynamic imports automatically handle code splitting and library loading. The primary waterfall to eliminate is **data loading** - fetching map data sequentially instead of in parallel with map initialization.

### Anti-Pattern: Sequential Data Loading

```javascript
// ❌ BAD: Data loads AFTER map initializes
async function initMap() {
  const map = new mapboxgl.Map({
    container: 'map',
    accessToken: MAPBOX_TOKEN,
    style: 'mapbox://styles/mapbox/streets-v12'
  });

  // Wait for map to load, THEN fetch data
  map.on('load', async () => {
    const data = await fetch('/api/data'); // Waterfall!
    map.addSource('data', { type: 'geojson', data: await data.json() });
  });
}
```

**Timeline:** Map init (0.5s) → Data fetch (1s) = **1.5s total**

### Solution: Parallel Data Loading

```javascript
// ✅ GOOD: Data fetch starts immediately
async function initMap() {
  // Start data fetch immediately (don't wait for map)
  const dataPromise = fetch('/api/data').then((r) => r.json());

  const map = new mapboxgl.Map({
    container: 'map',
    accessToken: MAPBOX_TOKEN,
    style: 'mapbox://styles/mapbox/streets-v12'
  });

  // Data is ready when map loads
  map.on('load', async () => {
    const data = await dataPromise;
    map.addSource('data', { type: 'geojson', data });
    map.addLayer({
      id: 'data-layer',
      type: 'circle',
      source: 'data'
    });
  });
}
```

**Timeline:** Max(map init, data fetch) = **~1s total**

### Set Precise Initial Viewport

```javascript
// ✅ Set exact center/zoom so the map fetches the right tiles immediately
const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  center: [-122.4194, 37.7749],
  zoom: 13
});

// Use 'idle' to know when the initial viewport is fully rendered
// (all tiles, sprites, and other resources are loaded; no transitions in progress)
map.once('idle', () => {
  console.log('Initial viewport fully rendered');
});
```

If you know the exact area users will see first, setting `center` and `zoom` upfront avoids the map starting at a default view and then panning/zooming to the target, which wastes tile fetches.

### Defer Non-Critical Features

```javascript
// ✅ Load critical features first, defer others
const map = new mapboxgl.Map({
  /* config */
});

map.on('load', () => {
  // 1. Add critical layers immediately
  addCriticalLayers(map);

  // 2. Defer secondary features
  // Note: Standard style 3D buildings can be toggled via config:
  // map.setConfigProperty('basemap', 'show3dObjects', false);
  requestIdleCallback(
    () => {
      addTerrain(map);
      addCustom3DLayers(map); // For classic styles with custom fill-extrusion layers
    },
    { timeout: 2000 }
  );

  // 3. Defer analytics and non-visual features
  setTimeout(() => {
    initializeAnalytics(map);
  }, 3000);
});
```

**Impact:** Significant reduction in time-to-interactive, especially when deferring terrain and 3D layers

---

## 🔴 Critical: Optimize Initial Bundle Size

**Problem:** Large bundles delay time-to-interactive on slow networks.

**Note:** Modern bundlers (Vite, Webpack, etc.) automatically handle code splitting for framework-based applications. The guidance below is most relevant for optimizing what gets bundled and when.

### Style JSON Bundle Impact

```javascript
// ❌ BAD: Inline massive style JSON (can be 500+ KB)
const style = {
  version: 8,
  sources: {
    /* 100s of lines */
  },
  layers: [
    /* 100s of layers */
  ]
};

// ✅ GOOD: Reference Mapbox-hosted styles
const map = new mapboxgl.Map({
  style: 'mapbox://styles/mapbox/streets-v12' // Fetched on demand
});

// ✅ OR: Store large custom styles externally
const map = new mapboxgl.Map({
  style: '/styles/custom-style.json' // Loaded separately
});
```

**Impact:** Reduces initial bundle by 30-50% when moving from inlined to hosted styles

---

## 🟡 High Impact: Optimize Marker Count

**Problem:** Too many markers causes slow rendering and interaction lag.

### Performance Thresholds

- **< 100 markers**: HTML markers OK (Marker class)
- **100-10,000 markers**: Use symbol layers (GPU-accelerated)
- **10,000+ markers**: Clustering recommended
- **100,000+ markers**: Vector tiles with server-side clustering

### Anti-Pattern: Thousands of HTML Markers

```javascript
// ❌ BAD: 5,000 HTML markers = 5+ second render, janky pan/zoom
restaurants.forEach((restaurant) => {
  const marker = new mapboxgl.Marker()
    .setLngLat([restaurant.lng, restaurant.lat])
    .setPopup(new mapboxgl.Popup().setHTML(restaurant.name))
    .addTo(map);
});
```

**Result:** 5,000 DOM elements, slow interactions, high memory

### Solution: Use Symbol Layers (GeoJSON)

```javascript
// ✅ GOOD: GPU-accelerated rendering, smooth at 10,000+ features
map.addSource('restaurants', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: restaurants.map((r) => ({
      type: 'Feature',
      geometry: { type: 'Point', coordinates: [r.lng, r.lat] },
      properties: { name: r.name, type: r.type }
    }))
  }
});

map.addLayer({
  id: 'restaurants',
  type: 'symbol',
  source: 'restaurants',
  layout: {
    'icon-image': 'restaurant',
    'icon-size': 0.8,
    'text-field': ['get', 'name'],
    'text-size': 12,
    'text-offset': [0, 1.5],
    'text-anchor': 'top'
  }
});

// Click handler (one listener for all features)
map.on('click', 'restaurants', (e) => {
  const feature = e.features[0];
  new mapboxgl.Popup().setLngLat(feature.geometry.coordinates).setHTML(feature.properties.name).addTo(map);
});
```

**Performance:** 10,000 features render in <100ms

### Solution: Clustering for High Density

```javascript
// ✅ GOOD: 50,000 markers → ~500 clusters at low zoom
map.addSource('restaurants', {
  type: 'geojson',
  data: restaurantsGeoJSON,
  cluster: true,
  clusterMaxZoom: 14, // Stop clustering at zoom 15
  clusterRadius: 50 // Radius relative to tile dimensions (512 = full tile width)
});

// Cluster circle layer
map.addLayer({
  id: 'clusters',
  type: 'circle',
  source: 'restaurants',
  filter: ['has', 'point_count'],
  paint: {
    'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 100, '#f1f075', 750, '#f28cb1'],
    'circle-radius': ['step', ['get', 'point_count'], 20, 100, 30, 750, 40]
  }
});

// Cluster count label
map.addLayer({
  id: 'cluster-count',
  type: 'symbol',
  source: 'restaurants',
  filter: ['has', 'point_count'],
  layout: {
    'text-field': '{point_count_abbreviated}',
    'text-size': 12
  }
});

// Individual point layer
map.addLayer({
  id: 'unclustered-point',
  type: 'circle',
  source: 'restaurants',
  filter: ['!', ['has', 'point_count']],
  paint: {
    'circle-color': '#11b4da',
    'circle-radius': 6
  }
});
```

**Impact:** 50,000 markers at 60 FPS with smooth interaction

---

## Summary: Performance Checklist

When building a Mapbox application, verify these optimizations in order:

### 🔴 Critical (Do First)

- [ ] Load map library and data in parallel (eliminate waterfalls)
- [ ] Use dynamic imports for map code (reduce initial bundle)
- [ ] Defer non-critical features (terrain, custom 3D layers, analytics)
- [ ] Use symbol layers for > 100 markers (not HTML markers)
- [ ] Implement viewport-based data loading for large datasets

### 🟡 High Impact

- [ ] Debounce/throttle map event handlers (geocode inputs, `moveend`)
- [ ] Optimize queryRenderedFeatures with layers filter and bounding box
- [ ] Use GeoJSON for < 5 MB, vector tiles for > 20 MB
- [ ] Always call map.remove() on cleanup in SPAs / page teardown
- [ ] Attach `map.on('error', …)` (or visible error UI) so style/tile/token failures are not silent
- [ ] Reuse popup instances (don't create on every interaction)
- [ ] Use feature state instead of dynamic layers for hover/selection
- [ ] Cluster demos: generate enough points to stress clustering (thousands, not a few hundred)

### Agent anti-pattern: happy-path only

First-pass agent code often ships a map with no `map.on('error')`, no `map.remove()`, and a tiny point set that never exercises `cluster: true`. Production demos need error visibility, teardown, and realistic scale.

### 🟢 Optimization

- [ ] Consolidate multiple layers with data-driven styling
- [ ] Add mobile-specific optimizations (circle layers, disabled rotation)
- [ ] Set minzoom/maxzoom on layers to avoid rendering at irrelevant zoom levels
- [ ] Avoid enabling preserveDrawingBuffer or antialias unless needed

### Measurement

```javascript
// Measure initial load time
console.time('map-load');
map.on('load', () => {
  console.timeEnd('map-load');
  // isStyleLoaded() returns true when style, sources, tiles, sprites, and models are all loaded
  console.log('Style loaded:', map.isStyleLoaded());
});

// Monitor frame rate
let frameCount = 0;
map.on('render', () => frameCount++);
setInterval(() => {
  console.log('FPS:', frameCount);
  frameCount = 0;
}, 1000);

// Check memory usage (Chrome DevTools -> Performance -> Memory)
```

**Target metrics:**

- **Time to Interactive:** < 2 seconds on 3G
- **Frame Rate:** 60 FPS during pan/zoom
- **Memory Growth:** < 10 MB per hour of usage
- **Bundle Size:** < 500 KB initial (map lazy-loaded)

---

## Reference Files

For detailed patterns on specific topics, load the corresponding reference file:

- **`references/data-loading.md`** — GeoJSON vs Vector Tiles decision matrix, viewport-based loading, progressive loading, vector tiles for large datasets
- **`references/interactions.md`** — Debounce/throttle events, optimize feature queries, batch DOM updates
- **`references/memory.md`** — Map cleanup patterns, popup/marker reuse, feature state vs dynamic layers
- **`references/mobile.md`** — Device detection, mobile-optimized layers, touch interaction, constructor options
- **`references/layers-styles.md`** — Consolidate layers with data-driven styling, simplify expressions, zoom-based visibility

© mapbox · MIT · mapbox/mapbox-agent-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой