Переход между версиями API

Google Maps JavaScript API развивается по версиям, которые отражают изменения в архитектуре, модели загрузки, системе ключей, а также в наборе доступных библиотек. Переход между версиями требует учета обратной совместимости, различий в загрузчике API и изменений в поведении объектов карты.

Основные поколения API

В контексте JavaScript API Google Maps можно выделить два ключевых поколения:

Legacy API (v3.x) Классическая версия, основанная на глобальном объекте google.maps. Подключение выполнялось через <script> с указанием параметра callback.

<script
  src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap"
  async
  defer
></script>

Основные характеристики:

  • глобальное пространство имен google.maps
  • синхронная модель инициализации через callback
  • широкая обратная совместимость
  • устаревающая система загрузки библиотек

Modern API (v3.49+ и loader @googlemaps/js-api-loader) Современная модель предполагает явную загрузку модулей и использование промисов.

import { Loader } from "@googlemaps/js-api-loader";

const loader = new Loader({
  apiKey: "API_KEY",
  version: "weekly",
  libraries: ["places"]
});

loader.load().then(async () => {
  const { Map } = await google.maps.importLibrary("maps");

  const map = new Map(document.getElementById("map"), {
    center: { lat: 55.7558, lng: 37.6173 },
    zoom: 10
  });
});

Ключевые особенности:

  • модульная загрузка через importLibrary
  • управление зависимостями библиотек
  • асинхронная инициализация
  • улучшенная производительность загрузки

Модель версионирования API

Google Maps JavaScript API использует несколько типов версий:

Weekly версия

version=weekly
  • содержит последние изменения
  • может включать экспериментальные улучшения
  • не гарантирует стабильность поведения

Используется в средах разработки и для тестирования новых возможностей.

Quarterly версия

version=quarterly
  • обновляется реже
  • предназначена для стабильных продакшн-систем
  • изменения проходят дополнительную проверку

Frozen версия

version=3.55
  • фиксированная версия API
  • поведение не изменяется со временем
  • используется для систем с жесткими требованиями к стабильности

Изменения в системе загрузки

Старый подход (script tag)

Ранее загрузка API строилась вокруг глобального объекта и callback-функции:

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.7128, lng: -74.0060 },
    zoom: 12
  });
}

Недостатки подхода:

  • невозможность точечного импорта модулей
  • увеличение времени загрузки при подключении всех библиотек
  • глобальное загрязнение пространства имен

Новый подход (динамическая загрузка)

Современный API отделяет загрузку ядра от библиотек:

const { Map } = await google.maps.importLibrary("maps");
const { Marker } = await google.maps.importLibrary("marker");

Преимущества:

  • загрузка только необходимых компонентов
  • улучшенная оптимизация bundle size
  • более предсказуемая асинхронная модель

Переход с глобального объекта google.maps

Одним из ключевых изменений является отказ от ожидания готовности глобального объекта.

Старый стиль

const map = new google.maps.Map(el, options);
const marker = new google.maps.Marker({
  position: { lat: 0, lng: 0 },
  map
});

Новый стиль

const { Map } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

const map = new Map(el, options);

new AdvancedMarkerElement({
  map,
  position: { lat: 0, lng: 0 }
});

Изменения:

  • Marker заменяется на AdvancedMarkerElement
  • явное разделение библиотек
  • строгая асинхронность загрузки

Изменения в работе с библиотеками

Ранее подключение дополнительных возможностей осуществлялось через параметр libraries:

&libraries=places,drawing,geometry

Проблемы:

  • все библиотеки загружались одновременно
  • невозможность динамического управления

Современная модель

await google.maps.importLibrary("places");
await google.maps.importLibrary("geometry");

Каждая библиотека:

  • загружается отдельно
  • может подключаться в момент необходимости
  • не влияет на стартовую загрузку карты

Совместимость версий

Обратная совместимость

Google Maps API сохраняет совместимость на уровне:

  • базовых классов (Map, LatLng)
  • основных событий (click, bounds_changed)
  • конфигураций карты

Однако изменения затрагивают:

  • расширенные маркеры
  • систему визуализации
  • некоторые вспомогательные сервисы

Проблемные зоны при миграции

Marker → AdvancedMarkerElement

Старый API:

new google.maps.Marker({
  position,
  map
});

Новый API:

new google.maps.marker.AdvancedMarkerElement({
  map,
  position
});

Изменения:

  • необходимость импорта marker библиотеки
  • отказ от части устаревших опций (например, animation)

PlacesService

Старая модель:

const service = new google.maps.places.PlacesService(map);

Новая модель:

const { PlacesService } = await google.maps.importLibrary("places");
const service = new PlacesService(map);

Изменение системы событий

Система событий сохраняет концепцию, но теперь теснее связана с модульной архитектурой.

map.addListener("click", (event) => {
  console.log(event.latLng.toJSON());
});

Различия:

  • события больше не зависят от глобального объекта
  • типизация и структуры событий стали строже
  • расширенные события доступны только через соответствующие библиотеки

Типизация и интеграция с TypeScript

Современная версия API ориентирована на TypeScript.

import { Loader } from "@googlemaps/js-api-loader";

const loader = new Loader({
  apiKey: "API_KEY",
  version: "weekly"
});

await loader.load();

const map: google.maps.Map = new google.maps.Map(
  document.getElementById("map") as HTMLElement,
  {
    center: { lat: 10, lng: 10 },
    zoom: 5
  }
);

Особенности:

  • строгие типы объектов
  • автодополнение в IDE
  • уменьшение ошибок при миграции

Различия в производительности

Переход между версиями API напрямую влияет на производительность:

Улучшения новой модели

  • уменьшение initial bundle size
  • lazy-loading библиотек
  • ускорение первого рендера карты
  • оптимизация сетевых запросов

Потенциальные проблемы

  • задержка при первом вызове importLibrary
  • необходимость управления состоянием загрузки
  • рост сложности архитектуры приложения

Управление ключами API

Старые и новые версии используют одинаковую систему ключей, однако появились дополнительные ограничения:

  • ограничение по HTTP referrer
  • обязательное включение billing account
  • более строгая проверка использования библиотек

Миграционный подход

Переход между версиями обычно выполняется поэтапно:

1. Переход на Loader

Замена script tag на @googlemaps/js-api-loader.

2. Перевод на importLibrary

Разделение логики загрузки по модулям.

3. Замена устаревших компонентов

  • Marker → AdvancedMarkerElement
  • PlacesService обновление
  • переход на новые overlay API

4. Оптимизация загрузки

  • lazy-load библиотек
  • разделение маршрутов приложения
  • контроль версий через weekly / quarterly

Изменения в архитектуре приложений

Старая архитектура строилась вокруг глобального состояния API:

  • один глобальный объект google.maps
  • синхронная инициализация
  • отсутствие явного контроля загрузки

Новая архитектура:

  • модульная загрузка
  • асинхронные зависимости
  • независимые сервисы карты
  • явное управление жизненным циклом компонентов

Поведение в многокартовых приложениях

Ранее несколько карт использовали общий глобальный контекст.

Теперь каждая карта:

  • инициирует собственный контекст библиотек
  • может использовать разные версии API
  • управляется независимо через importLibrary
const [mapsLib, markerLib] = await Promise.all([
  google.maps.importLibrary("maps"),
  google.maps.importLibrary("marker")
]);

Отладка и диагностика при переходе

При миграции часто возникают следующие проблемы:

  • отсутствие библиотеки в importLibrary
  • несоответствие версии API
  • конфликты старых глобальных вызовов
  • ошибки из-за устаревших классов

Диагностика обычно включает:

  • проверку network-запросов к maps.googleapis.com
  • анализ загрузки модулей
  • проверку консоли на предупреждения deprecation

Эволюция API как системы модулей

Переход между версиями отражает общий тренд:

  • отказ от монолитной загрузки
  • переход к модульной архитектуре
  • явное управление зависимостями
  • разделение ядра и расширений

Такая модель позволяет строить более масштабируемые и производительные клиентские приложения, работающие с картографическими данными.