All skills
mapbox avatar

/mapbox-web-performance-patterns

@f5ae7de official
by mapboxmapbox/mapbox-agent-skills80 stars
17

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.

Use this Skill: https://skilld.dev/gh/mapbox/mapbox-agent-skills/mapbox-web-performance-patterns

This session only. Nothing lands on disk.

referencesmemory.md

≈775 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Memory Management

Problem: Memory leaks cause browser tabs to become unresponsive over time. In SPAs that create/destroy map instances, this is a common production issue.

Always Clean Up Map Resources

// ✅ Essential cleanup pattern
function cleanupMap(map) {
  if (!map) return;

  // 1. Remove event listeners
  map.off('load', handleLoad);
  map.off('move', handleMove);

  // 2. Remove layers (if adding/removing dynamically)
  if (map.getLayer('dynamic-layer')) {
    map.removeLayer('dynamic-layer');
  }

  // 3. Remove sources (if adding/removing dynamically)
  if (map.getSource('dynamic-source')) {
    map.removeSource('dynamic-source');
  }

  // 4. Remove controls
  map.removeControl(navigationControl);

  // 5. CRITICAL: Remove map instance
  map.remove();
}

// React example
useEffect(() => {
  const map = new mapboxgl.Map({
    /* config */
  });

  return () => {
    cleanupMap(map); // Called on unmount
  };
}, []);

Clean Up Popups and Markers

// ❌ BAD: Creates new popup on every click (memory leak)
map.on('click', 'restaurants', (e) => {
  new mapboxgl.Popup().setLngLat(e.lngLat).setHTML(e.features[0].properties.name).addTo(map);
  // Popup never removed!
});

// ✅ GOOD: Reuse single popup instance
let popup = new mapboxgl.Popup({ closeOnClick: true });

map.on('click', 'restaurants', (e) => {
  popup.setLngLat(e.lngLat).setHTML(e.features[0].properties.name).addTo(map);
  // Previous popup content replaced, no leak
});

// Cleanup
function cleanup() {
  popup.remove();
  popup = null;
}

Use Feature State Instead of New Layers

// ❌ BAD: Create new layer for hover (memory overhead, causes re-render)
let hoveredFeatureId = null;

map.on('mousemove', 'restaurants', (e) => {
  if (map.getLayer('hover-layer')) {
    map.removeLayer('hover-layer');
  }
  map.addLayer({
    id: 'hover-layer',
    type: 'circle',
    source: 'restaurants',
    filter: ['==', ['id'], e.features[0].id],
    paint: { 'circle-color': 'yellow' }
  });
});

// ✅ GOOD: Use feature state (efficient, no layer creation)
map.on('mousemove', 'restaurants', (e) => {
  if (e.features.length > 0) {
    // Remove previous hover state
    if (hoveredFeatureId !== null) {
      map.setFeatureState({ source: 'restaurants', id: hoveredFeatureId }, { hover: false });
    }

    // Set new hover state
    hoveredFeatureId = e.features[0].id;
    map.setFeatureState({ source: 'restaurants', id: hoveredFeatureId }, { hover: true });
  }
});

// Style uses feature state
map.addLayer({
  id: 'restaurants',
  type: 'circle',
  source: 'restaurants',
  paint: {
    'circle-color': [
      'case',
      ['boolean', ['feature-state', 'hover'], false],
      '#ffff00', // Yellow when hover
      '#0000ff' // Blue otherwise
    ]
  }
});

Note: Feature state requires features to have IDs. Use generateId: true on the GeoJSON source to auto-assign IDs, or use promoteId to use an existing property as the feature ID.

Impact: Prevents memory growth from continuous layer churn over long sessions

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides a comprehensive set of performance optimization patterns and documentation for Mapbox GL JS applications. It focuses on legitimate development practices such as parallel data loading, bundle size optimization, and efficient marker rendering. No security risks or malicious patterns were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    1/2 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at f5ae7de. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 5 hours ago.

Activeupdated 2 months ago
  • Performance
  • mapbox
  • web
  • rendering
  • bundle-size
  • markers
  • geojson
  • memory
  • optimization

README badge

README badge for mapbox/mapbox-agent-skills/mapbox-web-performance-patterns

Provides performance optimization patterns for Mapbox GL JS applications, covering initialization waterfalls, bundle size, marker rendering, and memory management. Addresses critical issues like parallel data loading, symbol layers for large feature sets, and clustering strategies, with actionable code examples and performance thresholds.

Generated from the current SKILL.md.

Does this skill cover Mapbox GL JS only, or other Mapbox libraries?
This skill focuses on Mapbox GL JS web applications. It does not cover native mobile SDKs or server-side optimization.
What are the main performance bottlenecks this skill addresses?
The skill prioritizes initialization waterfalls (sequential data loading), bundle size, marker rendering (HTML vs symbol layers), and memory management. It covers the most impactful issues first, then optional optimizations.
When should I switch from HTML markers to symbol layers?
Use HTML markers for fewer than 100 markers. Switch to GPU-accelerated symbol layers for 100-10,000 markers, and add clustering for 10,000+ markers.
Does this skill provide code examples?
Yes. The skill includes concrete before/after code examples for initialization waterfalls, bundle optimization, marker strategies, and clustering patterns.

Generated from the current SKILL.md. These answers refresh after source changes.