Mapbox GL JS активно использует современные возможности JavaScript и Web API. Большинство современных браузеров поддерживают необходимые функции из коробки, однако при работе со старыми версиями браузеров возникают проблемы совместимости. В таких случаях используются polyfills — специальные библиотеки, реализующие отсутствующие возможности среды выполнения.
Polyfill представляет собой программную реализацию стандартного API, которая добавляет поддержку новых возможностей JavaScript в браузеры, где эти возможности отсутствуют.
Для Mapbox GL JS polyfills особенно важны при поддержке:
Современные версии Mapbox GL JS используют:
Если браузер не поддерживает один или несколько из перечисленных механизмов, приложение может завершиться ошибкой ещё до создания карты.
Типичные сообщения об ошибках:
Promise is undefined
Object doesn't support property or method 'assign'
Array.prototype.includes is undefined
fetch is not defined
В подобных ситуациях polyfills позволяют сохранить работоспособность приложения без изменения бизнес-логики.
Подход к совместимости зависит от версии библиотеки.
Версии Mapbox GL JS 0.x и 1.x поддерживали более широкий набор браузеров, включая Internet Explorer 11.
Пример:
Mapbox GL JS 1.x
├── Chrome
├── Firefox
├── Safari
├── Edge Legacy
└── IE11
Начиная с новых поколений библиотеки поддержка устаревших браузеров значительно сократилась.
Причины:
Поэтому при разработке корпоративных приложений с требованиями поддержки старых браузеров необходимо отдельно анализировать совместимость выбранной версии Mapbox GL JS.
Добавляют отсутствующие возможности языка JavaScript.
Наиболее востребованные:
Promise
Map
Set
WeakMap
Object.assign
Array.includes
Array.from
Обеспечивают поддержку Web API.
Примеры:
fetch
URL
requestAnimationFrame
Используются при работе с современными возможностями DOM.
Примеры:
Element.closest()
Element.matches()
CustomEvent
Одним из самых популярных наборов polyfills является библиотека core-js.
Установка:
npm install core-js
Подключение:
import "core-js/stable";
Либо выборочное подключение:
import "core-js/es/promise";
import "core-js/es/object/assign";
import "core-js/es/array/includes";
После загрузки polyfills Mapbox GL JS получает доступ к отсутствующим возможностям среды выполнения.
Mapbox GL JS активно использует асинхронное программирование.
Старые браузеры не поддерживают объект Promise.
Установка:
npm install es6-promise
Подключение:
import { polyfill } from "es6-promise";
polyfill();
После инициализации становится доступен стандартный API:
Promise.resolve("Mapbox");
Запросы к стилям, тайлам и геоданным часто используют Fetch API.
Установка:
npm install whatwg-fetch
Подключение:
import "whatwg-fetch";
После подключения появляется глобальная функция:
fetch("/data.json")
.then(response => response.json())
.then(data => console.log(data));
Для старых браузеров это особенно важно, поскольку отсутствие fetch вызывает критическую ошибку загрузки ресурсов.
Mapbox GL JS использует объединение объектов в различных внутренних механизмах.
Подключение через core-js:
import "core-js/es/object/assign";
Использование:
const result = Object.assign(
{},
defaults,
options
);
В старых браузерах без polyfill данный код завершится ошибкой.
Многие современные библиотеки используют метод includes().
Подключение:
import "core-js/es/array/includes";
Пример:
const layers = ["roads", "water"];
layers.includes("roads");
Без polyfill Internet Explorer не сможет выполнить подобный код.
Некоторые механизмы работы с адресами используют объект URL.
Подключение:
npm install url-polyfill
Импорт:
import "url-polyfill";
Пример:
const url = new URL(
"https://example.com/map?zoom=5"
);
console.log(url.searchParams.get("zoom"));
Часто polyfills применяются совместно с транспиляцией кода через Babel.
Установка:
npm install \
@babel/core \
@babel/preset-env \
babel-loader
Конфигурация:
module.exports = {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: 3
}
]
]
};
В этом режиме Babel автоматически анализирует код и добавляет только необходимые polyfills.
Преимущества:
Для корректной работы Babel обычно используется Browserslist.
Пример:
{
"browserslist": [
">0.5%",
"last 2 versions",
"not dead",
"IE 11"
]
}
На основе этих настроек Babel определяет набор необходимых polyfills.
Если проект не использует сборщик модулей, polyfills можно подключать через CDN.
Пример:
<script src="https://polyfill.io/v3/polyfill.min.js"></script>
После загрузки можно подключать Mapbox GL JS:
<script src="mapbox-gl.js"></script>
Такой подход часто встречается в небольших проектах и прототипах.
Polyfills должны загружаться раньше Mapbox GL JS.
Правильный порядок:
<script src="polyfills.js"></script>
<script src="mapbox-gl.js"></script>
<script src="app.js"></script>
Неправильный порядок:
<script src="mapbox-gl.js"></script>
<script src="polyfills.js"></script>
Во втором случае библиотека может завершить инициализацию с ошибкой ещё до загрузки polyfills.
Иногда требуется определить необходимость загрузки polyfills во время выполнения.
Пример:
if (!window.Promise) {
loadPromisePolyfill();
}
Проверка Fetch API:
if (!window.fetch) {
loadFetchPolyfill();
}
Проверка Object.assign:
if (!Object.assign) {
loadAssignPolyfill();
}
Такой подход позволяет загружать дополнительные ресурсы только при необходимости.
В крупных приложениях часто применяется динамический импорт.
Пример:
async function prepareBrowser() {
if (!window.fetch) {
await import("whatwg-fetch");
}
if (!window.Promise) {
await import("es6-promise");
}
}
После подготовки среды:
prepareBrowser()
.then(() => initializeMap());
Подобная схема уменьшает размер начальной загрузки для современных браузеров.
Mapbox GL JS активно использует Web Workers для обработки данных карты.
Важно понимать, что polyfills способны компенсировать отсутствие многих возможностей JavaScript, однако не могут полностью реализовать некоторые низкоуровневые браузерные механизмы.
Например:
Promise → polyfill возможен
Object.assign → polyfill возможен
Fetch API → polyfill возможен
Web Workers → полноценная замена невозможна
WebGL → полноценная замена невозможна
Если браузер не поддерживает WebGL, карта Mapbox GL JS работать не сможет независимо от количества подключённых polyfills.
Перед созданием карты рекомендуется убедиться в наличии WebGL.
Пример:
if (!mapboxgl.supported()) {
alert("WebGL не поддерживается");
}
Метод:
mapboxgl.supported()
проверяет наличие необходимых возможностей браузера.
Ошибка:
import "core-js/stable";
import "core-js/full";
В результате значительно увеличивается размер бандла.
Ошибка:
<script src="mapbox-gl.js"></script>
<script src="polyfills.js"></script>
Часть кода библиотеки уже выполнится без необходимой поддержки.
Некоторые старые polyfills могут конфликтовать с современными сборщиками.
Рекомендуется использовать актуальные версии:
core-js
whatwg-fetch
es6-promise
url-polyfill
Наличие polyfill не гарантирует полную работоспособность приложения.
Необходимо тестировать:
Для проектов, где требуется максимальная совместимость с устаревшими браузерами, обычно применяется следующий набор:
import "core-js/stable";
import "regenerator-runtime/runtime";
import "whatwg-fetch";
import "url-polyfill";
Конфигурация Babel:
{
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: 3
}
]
]
}
Проверка поддержки карты:
if (mapboxgl.supported()) {
initializeMap();
}
Такая комбинация обеспечивает поддержку большинства возможностей JavaScript, необходимых для работы Mapbox GL JS в устаревших браузерах, сохраняя при этом совместимость с современными инструментами сборки и разработки.