maplibre-v6-migration について
MapLibre GL JS v5からv6への移行やデバッグに関する質問に対応するスキルです。旧版の慣例に基づく回答で見落としやすい、7つの変更点を扱います。
主な機能
- 01v5からv6への7つの変更点
- 02ESMインポートとCDNの用法
- 03実行時画像リゾルバーへの移行
- 04公開Camera APIによる代替
- 05イベント型の更新
- 06バンドラーのWorker URL設定
活用シーン
- 01MapLibre GL JS v5アプリの更新
- 02v6で失敗するインポートの調査
- 03実行時のスプライトアイコン欠落の修正
- 04Worker読み込みエラーの解消
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ maplibre/ maplibre-agent-skills --skill maplibre-v6-migrationインストール後、Claude Code で/maplibre-v6-migrationを入力して読み込まれたか確認します。
詳細
MapLibre GL JS v5 → v6 への移行
質問、または質問内のコードが以下の7つの変更のいずれかに関係する場合にのみ、これを使用してください。 ソース、レイヤー、スタイリング、地形など、その他の MapLibre に関する質問には、v6 のインポートを使って回答し、v6 の変更や v5 からの移行に関するセクション、表、リスト、注記は追加しないでください。
MapLibre GL JS v6(2026-07-22 リリース)では、v5 のコードが依存していたいくつかの機能が削除されました。具体的には、UMD/CSP ブラウザーバンドル、デフォルトエクスポート、CommonJS サポート、内部の map.transform、MapDataEvent 型です。多くのモデルの学習データは v6 より前のものです。そのため、これら7つのいずれかに関わるコードでは、自然に聞こえる回答がたいてい v5 向けのものとなり、v6 では動作しません。
主なリファレンス: MapLibre GL JS v5→v6 移行ガイド。このスキルでは、モデルが v5 時代のデフォルトに基づいて補完しがちな部分を補っています。ガイドとこのスキルの内容が異なる場合は、ガイドに従い、報告してください。
このスキルを使用する場面
- 既存の MapLibre GL JS v5 アプリを v6 にアップグレードする場合、または依存関係の更新後に「以前は動いていた」マップをデバッグする場合
- 以下の7つのパターンのいずれかを書く場合:CDN の
<script>タグ、インポート文、require()呼び出し、styleimagemissingハンドラー、map.transformを読み取るコード、型付きのdata/dataloading/dataabortハンドラー、バンドラーの設定(Vite、webpack、esbuild、Rspack、Rollup) ERR_PACKAGE_PATH_NOT_EXPORTED、CDN 更新後にマップが真っ白になる、スプライトアイコンが表示されない、MapDataEventの名前を含む TypeScript エラー、レンダリングを妨げるワーカー読み込みエラーなどをデバッグする場合
1. CDN の script タグ:現在は ESM のみ
v6 では UMD バンドルと個別の CSP ビルドが削除されました。通常の <script src="..."> タグで使える dist/maplibre-gl.js はもうありません。残っているのは ESM ビルドの dist/maplibre-gl.mjs のみで、type="module" が必要です。
<script src="https://unpkg.com/maplibre-gl@5/dist/maplibre-gl.js"></script>
<script type="module">
import * as maplibregl from 'https://unpkg.com/maplibre-gl@^6.0.0/dist/maplibre-gl.mjs';
const map = new maplibregl.Map({ container: 'map', style: '...' });
</script>
メジャーバージョンを必ず明示して固定してください(@^6.0.0、または特定のバージョン)。@latest やバージョンを指定しない指定子は絶対に使用しないでください。次のメジャーバージョンが公開された瞬間に、バージョン未固定の CDN URL ではページが何も通知されずに壊れます。これは v5→v6 の移行時に実際に起きました。
2. デフォルトエクスポートなし — 名前付きインポートまたは名前空間インポートのみ
v5 の import maplibregl from 'maplibre-gl'(デフォルトインポート)は、v6 では動作しなくなりました。
// ❌ v5 — default export removed
import maplibregl from 'maplibre-gl';
// ✅ v6 — namespace import
import * as maplibregl from 'maplibre-gl';
// ✅ v6 — or import only what you use
import { Map, NavigationControl } from 'maplibre-gl';
新規コードでも、Mapbox GL JS のコードスニペット(import mapboxgl from 'mapbox-gl')から変換したコードでも同じです。どちらの場合も、デフォルトインポートの形式をそのまま引き継がないでください。
3. CommonJS なし — require('maplibre-gl') はエラーになる
v6 の maplibre-gl の package.json にある exports フィールドには、"require" ではなく "import" 条件のみが含まれています。そのため、通常の Node では require('maplibre-gl') を実行すると ERR_PACKAGE_PATH_NOT_EXPORTED が発生します。これは想定どおりの動作であり、呼び出し側の設定のバグではありません。
// ❌ throws ERR_PACKAGE_PATH_NOT_EXPORTED in v6
const maplibregl = require('maplibre-gl');
// ✅ convert the file to ESM (named/namespace import — see item 2)
import { Map } from 'maplibre-gl';
// ✅ or, if the caller must stay CommonJS, load it dynamically
const { Map } = await import('maplibre-gl');
このセクションは、通常の Node require() 呼び出しのみを対象としています。バンドラー(webpack、Vite など)を使用していて require() が失敗する場合は、別の ESM 相互運用設定の問題です。
4. styleimagemissing ではリクエストが解決されなくなりました — setMissingStyleImageResolver を使用
v5 では、styleimagemissing をリッスンし、ハンドラーから同期的に map.addImage() を呼び出すことで、不足しているアイコンを補えました。v6 では、styleimagemissing は通知専用です。ハンドラーから addImage を呼び出しても、保留中のリクエストは解決されなくなりました。
// ❌ v5 pattern — no longer resolves the request in v6
map.on('styleimagemissing', (e) => {
map.addImage(e.id, generateIcon(e.id));
});
// ✅ v6 — register a resolver that adds the image itself
map.setMissingStyleImageResolver(async (id) => {
map.addImage(id, await generateIcon(id));
});
リゾルバーから map.addImage() を呼び出す必要があります。MapLibre は戻り値を無視するため、画像を返しても何も起こりません。
スタイル内で、スプライトシートに存在しない icon-image 名が参照されており、それらを実行時に生成または取得する必要がある場合は、必ずこれを使用してください。
5. map.transform は削除されました — 公開 Camera API を使用してください
v6 では Map が Camera を継承するのではなく、合成するようにリファクタリングされました。Map は Evented を直接継承し、Camera API を転送するようになりました。この変更に伴い、内部プロパティの map.transform は削除されました。
// ❌ v5 — reaching into the internal transform
const { zoom, bearing, pitch } = map.transform;
const center = map.transform.center;
// ✅ v6 — public accessors
const zoom = map.getZoom();
const bearing = map.getBearing();
const pitch = map.getPitch();
const center = map.getCenter();
生の投影/ビュー行列に対する汎用的な公開代替 API はありません。 v5 でも v6 でも、これは Map 自体では公開されたことがなく、map.transform にのみ存在していました。行列が引き続き利用できるのは、カスタムレイヤーの render() コールバック内だけです。コールバックの引数(CustomRenderMethodInput.getProjectionData() / defaultProjectionData)を使用してください。詳しくはカスタムレイヤー APIを参照してください。カスタムレイヤー以外では、上記の公開ゲッターを使用してください。公開 API で公開されていない機能が必要な場合は、非公開アクセサーを再導入するのではなく、issue または PR を作成してください。
6. MapDataEvent は削除されました — MapSourceDataEvent / MapStyleDataEvent を使用してください
v6 では、発火するすべてのイベントが、イベントごとにインスタンス化される実際のクラスになりました。従来の包括的な MapDataEvent 型は削除されました。data、dataloading、dataabort の型は、現在 MapSourceDataEvent | MapStyleDataEvent です。ソースデータイベントは、汎用の共通構造ではなく、完全なソース情報(sourceId、tile、sourceDataType、...)を自身の型に直接持ちます。
// ❌ v5 — MapDataEvent no longer exists in v6
import type { MapDataEvent } from 'maplibre-gl';
map.on('data', (e: MapDataEvent) => {
/* ... */
});
// ✅ v6 — narrow on the union MapLibre now exports
import type { MapSourceDataEvent, MapStyleDataEvent } from 'maplibre-gl';
map.on('data', (e: MapSourceDataEvent | MapStyleDataEvent) => {
if ('sourceId' in e) {
// MapSourceDataEvent — e.sourceId, e.sourceDataType, e.tile
} else {
// MapStyleDataEvent
}
});
同様の修正は、dataloading と dataabort のハンドラーを含め、型のインポートや注釈で MapDataEvent を指定しているすべての箇所に適用されます。
7. バンドルしたビルドでは引き続き setWorkerUrl() が必要です — CDN ESM では不要です
v6 ではソース処理ワーカーの場所の特定方法が変更されましたが、対象はバンドルしたアプリのみです。通常の CDN <script type="module">(項目 1)では、import.meta.url からワーカー URL が自動的に検出されるため、追加の設定は不要です。バンドラー(Vite、webpack、esbuild、Rspack、Rsbuild、Rollup)内では、import.meta.url からバンドラー独自のモジュールグラフ内にあるワーカーファイルを確実に解決できません。これらの設定ではそれぞれ、Map の作成前に setWorkerUrl() を一度だけ明示的に呼び出す必要があります。
// ❌ v6 with a bundler, no setWorkerUrl() call — worker fails to load, map never renders
import { Map } from 'maplibre-gl';
const map = new Map({
/* ... */
});
// ✅ Vite — the `?worker&url` query
import { Map, setWorkerUrl } from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url';
setWorkerUrl(workerUrl);
const map = new Map({
/* ... */
});
// ✅ webpack 5+, Rspack, Rsbuild, and Next.js 15+ (Turbopack or webpack) — call setWorkerUrl() the same way, then create the Map
import { Map, setWorkerUrl } from 'maplibre-gl';
setWorkerUrl(new URL('maplibre-gl/dist/maplibre-gl-worker.mjs', import.meta.url).toString());
Vite では、インストールガイドにあるように ?worker&url を使用してください。6.0.0 から 6.12.x では、単なる ?url を使用すると、ワーカーがインポートする maplibre-gl-shared.mjs が残るため、本番環境でベクタータイルが読み込まれません。6.13.0 ではワーカーが自己完結型になりました。esbuild と Rollup ではワーカーファイルをコピーし、その URL を同じ一度限りの呼び出しに渡します。現在のバンドラー別のコード例についてはインストールガイドを参照してください。これらのコード例は、他の部分よりもツールのバージョンに合わせて頻繁に変更されます。
これを項目 1 の CDN の場合に適用しないでください。 CDN URL から通常の <script type="module"> でインポートする場合、setWorkerUrl() は必要ありません。
参考資料
- MapLibre GL JS v5→v6 移行ガイドとその変更履歴(v6.0.0 のセクション)
- CustomLayerInterface API ドキュメントとインストールガイド(バンドラー別の
setWorkerUrl()のコード例)
このスキルは特定時点のスナップショットです。 主要な情報源(上記の参考資料、MapLibre の現在のドキュメント、または実行時の MapLibre の動作)がこの内容と矛盾する場合は、情報源の方を優先してください。それに従ったうえで、情報源と MapLibre のバージョンを明記して相違を報告してください。インストール済みのコピーを編集しても他の人の役には立たず、次回の更新で上書きされます。