Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问许可证需确认审计提醒

mapbox-web-performance-patternsMapbox Web 性能模式

Agent Skill

mapbox-web-performance-patterns 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

20,686

周安装

845

GitHub Stars

47

下载量

6,625
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:mapbox-web-performance-patterns(Mapbox Web 性能模式)
来源仓库:https://github.com/mapbox/mapbox-agent-skills
仓库路径:skills/mapbox-web-performance-patterns
安装命令:
npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-web-performance-patterns
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-web-performance-patterns

简介

Mapbox GL JS 应用程序的性能优化模式,按用户影响确定优先级。

  • 通过与地图初始化并行加载地图数据来消除初始化瀑布,并设置精确的视口以避免冗余图块获取
  • 使用符号层处理 100 多个标记(GPU 加速),并使用聚类处理 10,000 多个特征;避免大规模 HTML 标记
  • 对于 5 MB 以下的数据集选择 GeoJSON,对于 20 MB 以上的数据集选择矢量切片;实施基于视口的加载以减少带宽
  • 始终调用map.remove()
  • 在单页应用程序中进行清理以防止内存泄漏;重用弹出实例并使用特征状态来实现悬停效果而不是动态图层
  • Debounce/throttle 事件处理程序,优化 queryRenderedFeatures()
  • 使用图层过滤器,并将非关键功能(地形、3D 图层)推迟到初始渲染之后

SKILL.md

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

// ❌ 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

// ✅ 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

// ✅ 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

// ✅ 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

// ❌ 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

// ❌ 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)

// ✅ 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

// ✅ 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
  • 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
  • Reuse popup instances (don't create on every interaction)
  • Use feature state instead of dynamic layers for hover/selection

🟢 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

// 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

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

37.76%
按下载量换算2,502

Claude

31.81%
按下载量换算2,107

Cursor

17.63%
按下载量换算1,168

Gemini CLI

10.57%
按下载量换算700

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills