mapbox-maplibre-migration by mapbox/mapbox-agent-skills
npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-maplibre-migration从 MapLibre GL JS 迁移到 Mapbox GL JS 的专家指导。涵盖共享历史、API 兼容性、迁移步骤以及 Mapbox 平台的优势。
MapLibre GL JS 是 Mapbox GL JS v1.13.0 的一个开源分支,创建于 2020 年 12 月,当时 Mapbox 从 v2.0 开始更改了其许可证。
时间线:
关键见解: 由于 MapLibre 始于 Mapbox 的一个分支,两者的 API 约 95% 相同。大多数代码只需极少的改动即可在两者中运行,使得迁移变得直接明了。
选择 Mapbox GL JS 的令人信服的理由:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Mapbox 提供慷慨的免费层级: 每月 50,000 次地图加载,使其适用于许多无需成本的应用程序。
| 方面 | Mapbox GL JS | MapLibre GL JS |
|---|---|---|
| 许可证 | 专有(v2+) | BSD 3-Clause(开源) |
| 支持 | 官方商业支持 | 社区支持 |
| 瓦片 | 高级 Mapbox 矢量瓦片 | OSM 或自定义瓦片源 |
| 卫星 | 高质量的全球图像 | 需要自定义源 |
| 令牌 | 必需(访问令牌) | 可选(取决于瓦片源) |
| API | 完整的 Mapbox 生态系统 | 需要第三方服务 |
| Studio | 完全集成 | 无原生集成 |
| 3D 地形 | 内置高级数据 | 可用(需要数据源) |
| 地球视图 | v2.9+ | v3.0+ |
| API 兼容性 | 与 MapLibre 约 95% 兼容 | 与 Mapbox 约 95% 兼容 |
| 包大小 | ~500KB | ~450KB |
| 设置复杂度 | 简单(只需添加令牌) | 需要瓦片源设置 |
pk. 开头)# 移除 MapLibre
npm uninstall maplibre-gl
# 安装 Mapbox
npm install mapbox-gl
// 之前(MapLibre)
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
// 之后(Mapbox)
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
或使用 CDN:
<!-- 之前(MapLibre) -->
<script src="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.css" rel="stylesheet" />
<!-- 之后(Mapbox) -->
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css" rel="stylesheet" />
// 在地图初始化之前添加此行
mapboxgl.accessToken = 'pk.your_mapbox_access_token';
令牌最佳实践:
process.env.VITE_MAPBOX_TOKEN 或 process.env.NEXT_PUBLIC_MAPBOX_TOKENpk.*).env 和 .gitignore)有关全面的令牌安全指导,请参阅 mapbox-token-security 技能。
// 之前(MapLibre)
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json', // 或您的自定义样式
center: [-122.4194, 37.7749],
zoom: 12
});
// 之后(Mapbox)
mapboxgl.accessToken = 'pk.your_mapbox_access_token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/standard', // Mapbox 样式
center: [-122.4194, 37.7749],
zoom: 12
});
Mapbox 提供专业设计、维护的样式:
// Mapbox 内置样式
style: 'mapbox://styles/mapbox/standard'; // Mapbox Standard(默认)
style: 'mapbox://styles/mapbox/standard-satellite'; // Mapbox Standard Satellite
style: 'mapbox://styles/mapbox/streets-v12'; // Streets v12
style: 'mapbox://styles/mapbox/satellite-v9'; // 卫星图像
style: 'mapbox://styles/mapbox/satellite-streets-v12'; // 混合
style: 'mapbox://styles/mapbox/outdoors-v12'; // 户外/休闲
style: 'mapbox://styles/mapbox/light-v11'; // 浅色主题
style: 'mapbox://styles/mapbox/dark-v11'; // 深色主题
style: 'mapbox://styles/mapbox/navigation-day-v1'; // 导航(日间)
style: 'mapbox://styles/mapbox/navigation-night-v1'; // 导航(夜间)
自定义样式: 您也可以从 Mapbox Studio 创建和使用自定义样式:
style: 'mapbox://styles/your-username/your-style-id';
将所有 maplibregl 引用替换为 mapboxgl:
// 标记
const marker = new mapboxgl.Marker() // 之前是:maplibregl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new mapboxgl.Popup().setText('San Francisco'))
.addTo(map);
// 控件
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
map.addControl(new mapboxgl.GeolocateControl());
map.addControl(new mapboxgl.FullscreenControl());
map.addControl(new mapboxgl.ScaleControl());
一些 MapLibre 插件应替换为 Mapbox 版本:
| MapLibre 插件 | Mapbox 替代方案 |
|---|---|
@maplibre/maplibre-gl-geocoder | @mapbox/mapbox-gl-geocoder |
@maplibre/maplibre-gl-draw | @mapbox/mapbox-gl-draw |
maplibre-gl-compare | mapbox-gl-compare |
示例:
// 之前(MapLibre)
import MaplibreGeocoder from '@maplibre/maplibre-gl-geocoder';
// 之后(Mapbox)
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
map.addControl(
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
mapboxgl: mapboxgl
})
);
您所有的地图代码、事件、图层和源都完全相同地工作:
// 这段代码在两个库中完全一样地工作
map.on('load', () => {
map.addSource('points', {
type: 'geojson',
data: geojsonData
});
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
paint: {
'circle-radius': 8,
'circle-color': '#ff0000'
}
});
});
// 事件完全相同地工作
map.on('click', 'points-layer', (e) => {
console.log(e.features[0].properties);
});
// 所有地图方法工作方式相同
map.setCenter([lng, lat]);
map.setZoom(12);
map.fitBounds(bounds);
map.flyTo({ center: [lng, lat], zoom: 14 });
必须更改:
maplibre-gl → mapbox-gl)mapboxgl.accessToken 配置mapbox:// 样式)完全保持不变:
setCenter、setZoom、fitBounds、flyTo 等)map.on('click')、map.on('load') 等)这些在两个库中工作完全相同:
// 地图方法
map.setCenter([lng, lat]);
map.setZoom(zoom);
map.fitBounds(bounds);
map.panTo([lng, lat]);
map.flyTo({ center, zoom });
map.getCenter();
map.getZoom();
map.getBounds();
map.resize();
// 事件
map.on('load', callback);
map.on('click', callback);
map.on('move', callback);
map.on('zoom', callback);
map.on('rotate', callback);
// 标记
new mapboxgl.Marker();
marker.setLngLat([lng, lat]);
marker.setPopup(popup);
marker.addTo(map);
marker.remove();
marker.setDraggable(true);
// 弹出窗口
new mapboxgl.Popup();
popup.setLngLat([lng, lat]);
popup.setHTML(html);
popup.setText(text);
popup.addTo(map);
// 源和图层
map.addSource(id, source);
map.removeSource(id);
map.addLayer(layer);
map.removeLayer(id);
map.getSource(id);
map.getLayer(id);
// 样式
map.setPaintProperty(layerId, property, value);
map.setLayoutProperty(layerId, property, value);
map.setFilter(layerId, filter);
// 控件
map.addControl(control, position);
new mapboxgl.NavigationControl();
new mapboxgl.GeolocateControl();
new mapboxgl.FullscreenControl();
new mapboxgl.ScaleControl();
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
// OSM 瓦片不需要令牌
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [-122.4194, 37.7749],
zoom: 12
});
map.on('load', () => {
new maplibregl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new maplibregl.Popup().setText('San Francisco'))
.addTo(map);
});
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// 添加您的 Mapbox 令牌
mapboxgl.accessToken = 'pk.your_mapbox_access_token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749],
zoom: 12
});
map.on('load', () => {
new mapboxgl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new mapboxgl.Popup().setText('San Francisco'))
.addTo(map);
});
不同之处: 包、导入、令牌和样式 URL。其他一切都相同。
迁移后,您可以访问这些仅 Mapbox 提供的功能:
将这些 API 与您的地图结合使用以增强功能:
// 地理编码 API - 将地址转换为坐标
const response = await fetch(
`https://api.mapbox.com/search/geocode/v6/forward?q=San+Francisco&access_token=${mapboxgl.accessToken}`
);
// 路线 API - 获取逐向导航路线
const directions = await fetch(
`https://api.mapbox.com/directions/v5/mapbox/driving/-122.42,37.78;-122.45,37.76?access_token=${mapboxgl.accessToken}`
);
// 等时线 API - 计算行程时间多边形
const isochrone = await fetch(
`https://api.mapbox.com/isochrone/v1/mapbox/driving/-122.42,37.78?contours_minutes=5,10,15&access_token=${mapboxgl.accessToken}`
);
迁移在所有框架中工作方式相同。有关详细的 React、Vue、Svelte、Angular 模式,请参阅 mapbox-web-integration-patterns 技能。
import { useRef, useEffect } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// 设置令牌一次(可以在应用初始化时进行)
mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_TOKEN;
function MapComponent() {
const mapRef = useRef(null);
const mapContainerRef = useRef(null);
useEffect(() => {
mapRef.current = new mapboxgl.Map({
container: mapContainerRef.current,
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749],
zoom: 12
});
return () => {
mapRef.current.remove();
};
}, []);
return <div ref={mapContainerRef} style={{ height: '100vh' }} />;
}
只需将 maplibregl 替换为 mapboxgl 并更新令牌/样式 - 其他一切都相同!
<template>
<div ref="mapContainer" class="map-container"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN;
const mapContainer = ref(null);
let map = null;
onMounted(() => {
map = new mapboxgl.Map({
container: mapContainer.value,
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749],
zoom: 12
});
});
onUnmounted(() => {
map?.remove();
});
</script>
<style scoped>
.map-container {
height: 100vh;
}
</style>
问题:
// 错误:"使用 Mapbox GL 需要一个有效的 Mapbox 访问令牌"
const map = new mapboxgl.Map({...});
解决方案:
// 在创建地图之前设置令牌
mapboxgl.accessToken = 'pk.your_token';
const map = new mapboxgl.Map({...});
问题:
// 令牌硬编码在源代码中
mapboxgl.accessToken = 'pk.eyJ1Ijoi...';
解决方案:
// 使用环境变量
mapboxgl.accessToken = process.env.VITE_MAPBOX_TOKEN;
// 添加到 .env 文件(不提交到 git)
VITE_MAPBOX_TOKEN=pk.your_token
// 将 .env 添加到 .gitignore
echo ".env" >> .gitignore
问题:
// MapLibre 风格的 URL 无法达到最佳效果
style: 'https://demotiles.maplibre.org/style.json';
解决方案:
// 使用 Mapbox 样式 URL 以获得更好的性能和功能
style: 'mapbox://styles/mapbox/streets-v12';
问题:
// MapLibre 插件无法工作
import MaplibreGeocoder from '@maplibre/maplibre-gl-geocoder';
解决方案:
// 使用 Mapbox 插件
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
问题:
// 错误的 CDN
<script src="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.js"></script>
解决方案:
// 使用 Mapbox CDN
<script src='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css' rel='stylesheet' />
完成以下步骤以确保迁移成功:
npm install mapbox-gl(移除 maplibre-gl)maplibre-gl → mapbox-glmaplibre-gl.css → mapbox-gl.cssmapboxgl.accessToken = 'pk.xxx'.env 中mapbox://styles/mapbox/streets-v12maplibregl. 替换为 mapboxgl.可靠性与支持:
性能:
功能:
开发者体验:
@types/mapbox-gl)生态系统集成:
可预测的成本:
合规性与安全性:
无基础设施负担:
由于共享相同的核心代码库,两个库具有相似的渲染性能:
| 指标 | Mapbox GL JS | MapLibre GL JS |
|---|---|---|
| 包大小 | ~500KB | ~450KB |
| 初始加载 | 相似 | 相似 |
| 渲染 | 基于 WebGL | 基于 WebGL |
| 内存使用 | 相似 | 相似 |
| 瓦片加载 | 更快(CDN + 优化瓦片) | 取决于瓦片源 |
关键见解: 根据功能、支持和瓦片质量进行选择,而不是渲染性能。Mapbox 的优势在于瓦片交付速度、数据质量和生态系统集成。
相关技能:
Mapbox GL JS:
迁移支持:
| 项目 | MapLibre | Mapbox |
|---|---|---|
| 包 | maplibre-gl | mapbox-gl |
| 导入 | import maplibregl from 'maplibre-gl' | import mapboxgl from 'mapbox-gl' |
| 令牌 | 可选(取决于瓦片) | 必需:mapboxgl.accessToken = 'pk.xxx' |
| 样式 | 自定义 URL 或 OSM 瓦片 | mapbox://styles/mapbox/streets-v12 |
| 许可证 | BSD(开源) | 专有(v2+) |
| 支持 | 社区 | 官方商业支持 |
| 瓦片 | 需要瓦片源 | 包含高级 Mapbox 瓦片 |
| API | 第三方 | 完整的 Mapbox API 生态系统 |
| API | 约 95% 兼容 | 约 95% 兼容 |
结论: 迁移很容易,因为 API 几乎相同。主要更改是打包、令牌设置和样式 URL。结果是能够访问 Mapbox 的高级瓦片、生态系统和支持。
每周安装量
183
仓库
GitHub 星标数
35
首次出现
2026年2月3日
安全审计
安装于
gemini-cli163
opencode162
codex159
github-copilot157
cursor153
kimi-cli149
Expert guidance for migrating from MapLibre GL JS to Mapbox GL JS. Covers the shared history, API compatibility, migration steps, and the advantages of Mapbox's platform.
MapLibre GL JS is an open-source fork of Mapbox GL JS v1.13.0 , created in December 2020 when Mapbox changed their license starting with v2.0.
Timeline:
Key Insight: The APIs are ~95% identical because MapLibre started as a Mapbox fork. Most code works in both with minimal changes, making migration straightforward.
Compelling reasons to choose Mapbox GL JS:
Mapbox offers a generous free tier: 50,000 map loads/month, making it suitable for many applications without cost.
| Aspect | Mapbox GL JS | MapLibre GL JS |
|---|---|---|
| License | Proprietary (v2+) | BSD 3-Clause (Open Source) |
| Support | Official commercial support | Community support |
| Tiles | Premium Mapbox vector tiles | OSM or custom tile sources |
| Satellite | High-quality global imagery | Requires custom source |
| Token | Required (access token) | Optional (depends on tile source) |
| APIs | Full Mapbox ecosystem | Requires third-party services |
| Studio | Full integration | No native integration |
| 3D Terrain |
pk. for public tokens)# Remove MapLibre
npm uninstall maplibre-gl
# Install Mapbox
npm install mapbox-gl
// Before (MapLibre)
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
// After (Mapbox)
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
Or with CDN:
<!-- Before (MapLibre) -->
<script src="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.css" rel="stylesheet" />
<!-- After (Mapbox) -->
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css" rel="stylesheet" />
// Add this before map initialization
mapboxgl.accessToken = 'pk.your_mapbox_access_token';
Token best practices:
process.env.VITE_MAPBOX_TOKEN or process.env.NEXT_PUBLIC_MAPBOX_TOKENpk.*) for client-side code.env and .gitignore)See mapbox-token-security skill for comprehensive token security guidance.
// Before (MapLibre)
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json', // or your custom style
center: [-122.4194, 37.7749],
zoom: 12
});
// After (Mapbox)
mapboxgl.accessToken = 'pk.your_mapbox_access_token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/standard', // Mapbox style
center: [-122.4194, 37.7749],
zoom: 12
});
Mapbox provides professionally designed, maintained styles:
// Mapbox built-in styles
style: 'mapbox://styles/mapbox/standard'; // Mapbox Standard (default)
style: 'mapbox://styles/mapbox/standard-satellite'; // Mapbox Standard Satellite
style: 'mapbox://styles/mapbox/streets-v12'; // Streets v12
style: 'mapbox://styles/mapbox/satellite-v9'; // Satellite imagery
style: 'mapbox://styles/mapbox/satellite-streets-v12'; // Hybrid
style: 'mapbox://styles/mapbox/outdoors-v12'; // Outdoor/recreation
style: 'mapbox://styles/mapbox/light-v11'; // Light theme
style: 'mapbox://styles/mapbox/dark-v11'; // Dark theme
style: 'mapbox://styles/mapbox/navigation-day-v1'; // Navigation (day)
style: 'mapbox://styles/mapbox/navigation-night-v1'; // Navigation (night)
Custom styles: You can also create and use custom styles from Mapbox Studio:
style: 'mapbox://styles/your-username/your-style-id';
Replace all maplibregl references with mapboxgl:
// Markers
const marker = new mapboxgl.Marker() // was: maplibregl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new mapboxgl.Popup().setText('San Francisco'))
.addTo(map);
// Controls
map.addControl(new mapboxgl.NavigationControl(), 'top-right');
map.addControl(new mapboxgl.GeolocateControl());
map.addControl(new mapboxgl.FullscreenControl());
map.addControl(new mapboxgl.ScaleControl());
Some MapLibre plugins should be replaced with Mapbox versions:
| MapLibre Plugin | Mapbox Alternative |
|---|---|
@maplibre/maplibre-gl-geocoder | @mapbox/mapbox-gl-geocoder |
@maplibre/maplibre-gl-draw | @mapbox/mapbox-gl-draw |
maplibre-gl-compare | mapbox-gl-compare |
Example:
// Before (MapLibre)
import MaplibreGeocoder from '@maplibre/maplibre-gl-geocoder';
// After (Mapbox)
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
map.addControl(
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
mapboxgl: mapboxgl
})
);
All your map code, events, layers, and sources work identically:
// This code works EXACTLY THE SAME in both libraries
map.on('load', () => {
map.addSource('points', {
type: 'geojson',
data: geojsonData
});
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
paint: {
'circle-radius': 8,
'circle-color': '#ff0000'
}
});
});
// Events work identically
map.on('click', 'points-layer', (e) => {
console.log(e.features[0].properties);
});
// All map methods work the same
map.setCenter([lng, lat]);
map.setZoom(12);
map.fitBounds(bounds);
map.flyTo({ center: [lng, lat], zoom: 14 });
Must change:
maplibre-gl → mapbox-gl)mapboxgl.accessToken configurationmapbox:// styles)Stays exactly the same:
setCenter, setZoom, fitBounds, flyTo, etc.)map.on('click'), map.on('load'), etc.)These work identically in both libraries:
// Map methods
map.setCenter([lng, lat]);
map.setZoom(zoom);
map.fitBounds(bounds);
map.panTo([lng, lat]);
map.flyTo({ center, zoom });
map.getCenter();
map.getZoom();
map.getBounds();
map.resize();
// Events
map.on('load', callback);
map.on('click', callback);
map.on('move', callback);
map.on('zoom', callback);
map.on('rotate', callback);
// Markers
new mapboxgl.Marker();
marker.setLngLat([lng, lat]);
marker.setPopup(popup);
marker.addTo(map);
marker.remove();
marker.setDraggable(true);
// Popups
new mapboxgl.Popup();
popup.setLngLat([lng, lat]);
popup.setHTML(html);
popup.setText(text);
popup.addTo(map);
// Sources & Layers
map.addSource(id, source);
map.removeSource(id);
map.addLayer(layer);
map.removeLayer(id);
map.getSource(id);
map.getLayer(id);
// Styling
map.setPaintProperty(layerId, property, value);
map.setLayoutProperty(layerId, property, value);
map.setFilter(layerId, filter);
// Controls
map.addControl(control, position);
new mapboxgl.NavigationControl();
new mapboxgl.GeolocateControl();
new mapboxgl.FullscreenControl();
new mapboxgl.ScaleControl();
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
// No token needed for OSM tiles
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [-122.4194, 37.7749],
zoom: 12
});
map.on('load', () => {
new maplibregl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new maplibregl.Popup().setText('San Francisco'))
.addTo(map);
});
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// Add your Mapbox token
mapboxgl.accessToken = 'pk.your_mapbox_access_token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749],
zoom: 12
});
map.on('load', () => {
new mapboxgl.Marker()
.setLngLat([-122.4194, 37.7749])
.setPopup(new mapboxgl.Popup().setText('San Francisco'))
.addTo(map);
});
What's different: Package, import, token, and style URL. Everything else is identical.
After migration, you gain access to these Mapbox-only features:
Use these APIs alongside your map for enhanced functionality:
// Geocoding API - Convert addresses to coordinates
const response = await fetch(
`https://api.mapbox.com/search/geocode/v6/forward?q=San+Francisco&access_token=${mapboxgl.accessToken}`
);
// Directions API - Get turn-by-turn directions
const directions = await fetch(
`https://api.mapbox.com/directions/v5/mapbox/driving/-122.42,37.78;-122.45,37.76?access_token=${mapboxgl.accessToken}`
);
// Isochrone API - Calculate travel time polygons
const isochrone = await fetch(
`https://api.mapbox.com/isochrone/v1/mapbox/driving/-122.42,37.78?contours_minutes=5,10,15&access_token=${mapboxgl.accessToken}`
);
Migration works identically across all frameworks. See mapbox-web-integration-patterns skill for detailed React, Vue, Svelte, Angular patterns.
import { useRef, useEffect } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// Set token once (can be in app initialization)
mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_TOKEN;
function MapComponent() {
const mapRef = useRef(null);
const mapContainerRef = useRef(null);
useEffect(() => {
mapRef.current = new mapboxgl.Map({
container: mapContainerRef.current,
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749],
zoom: 12
});
return () => {
mapRef.current.remove();
};
}, []);
return <div ref={mapContainerRef} style={{ height: '100vh' }} />;
}
Just replace maplibregl with mapboxgl and update token/style - everything else is identical!
<template>
<div ref="mapContainer" class="map-container"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN;
const mapContainer = ref(null);
let map = null;
onMounted(() => {
map = new mapboxgl.Map({
container: mapContainer.value,
style: 'mapbox://styles/mapbox/streets-v12',
center: [-122.4194, 37.7749],
zoom: 12
});
});
onUnmounted(() => {
map?.remove();
});
</script>
<style scoped>
.map-container {
height: 100vh;
}
</style>
Problem:
// Error: "A valid Mapbox access token is required to use Mapbox GL"
const map = new mapboxgl.Map({...});
Solution:
// Set token BEFORE creating map
mapboxgl.accessToken = 'pk.your_token';
const map = new mapboxgl.Map({...});
Problem:
// Token hardcoded in source
mapboxgl.accessToken = 'pk.eyJ1Ijoi...';
Solution:
// Use environment variables
mapboxgl.accessToken = process.env.VITE_MAPBOX_TOKEN;
// Add to .env file (not committed to git)
VITE_MAPBOX_TOKEN=pk.your_token
// Add .env to .gitignore
echo ".env" >> .gitignore
Problem:
// MapLibre-style URL won't work optimally
style: 'https://demotiles.maplibre.org/style.json';
Solution:
// Use Mapbox style URL for better performance and features
style: 'mapbox://styles/mapbox/streets-v12';
Problem:
// MapLibre plugin won't work
import MaplibreGeocoder from '@maplibre/maplibre-gl-geocoder';
Solution:
// Use Mapbox plugin
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
Problem:
// Wrong CDN
<script src="https://unpkg.com/maplibre-gl@3.0.0/dist/maplibre-gl.js"></script>
Solution:
// Use Mapbox CDN
<script src='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css' rel='stylesheet' />
Complete these steps for a successful migration:
npm install mapbox-gl (remove maplibre-gl)maplibre-gl → mapbox-glmaplibre-gl.css → mapbox-gl.cssmapboxgl.accessToken = 'pk.xxx'.envmapbox://styles/mapbox/streets-v12Reliability & Support:
Performance:
Features:
Developer Experience:
@types/mapbox-gl)Ecosystem Integration:
Predictable Costs:
Compliance & Security:
No Infrastructure Burden:
Both libraries have similar rendering performance as they share the same core codebase:
| Metric | Mapbox GL JS | MapLibre GL JS |
|---|---|---|
| Bundle size | ~500KB | ~450KB |
| Initial load | Similar | Similar |
| Rendering | WebGL-based | WebGL-based |
| Memory usage | Similar | Similar |
| Tile loading | Faster (CDN + optimized tiles) | Depends on tile source |
Key insight: Choose based on features, support, and tile quality, not rendering performance. Mapbox's advantage is in tile delivery speed, data quality, and ecosystem integration.
Related skills:
Mapbox GL JS:
Migration Support:
| What | MapLibre | Mapbox |
|---|---|---|
| Package | maplibre-gl | mapbox-gl |
| Import | import maplibregl from 'maplibre-gl' | import mapboxgl from 'mapbox-gl' |
| Token | Optional (depends on tiles) | Required: mapboxgl.accessToken = 'pk.xxx' |
| Style | Custom URL or OSM tiles | mapbox://styles/mapbox/streets-v12 |
Bottom line: Migration is easy because APIs are nearly identical. Main changes are packaging, token setup, and style URLs. The result is access to Mapbox's premium tiles, ecosystem, and support.
Weekly Installs
183
Repository
GitHub Stars
35
First Seen
Feb 3, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
gemini-cli163
opencode162
codex159
github-copilot157
cursor153
kimi-cli149
Vue.js测试最佳实践:Vue 3组件、组合式函数、Pinia与异步测试完整指南
3,900 周安装
| Built-in with premium data |
| Available (requires data source) |
| Globe View | v2.9+ | v3.0+ |
| API Compatibility | ~95% compatible with MapLibre | ~95% compatible with Mapbox |
| Bundle Size | ~500KB | ~450KB |
| Setup Complexity | Easy (just add token) | Requires tile source setup |
maplibregl. with mapboxgl.| License | BSD (Open Source) | Proprietary (v2+) |
| Support | Community | Official commercial support |
| Tiles | Requires tile source | Premium Mapbox tiles included |
| APIs | Third-party | Full Mapbox API ecosystem |
| API | ~95% compatible | ~95% compatible |