Статические карты для SSR

Архитектура SSR (Server-Side Rendering) в веб-приложениях предъявляет особые требования к интеграции картографических сервисов, поскольку классический подход с загрузкой и инициализацией Google Maps JavaScript API рассчитан на выполнение в браузере и опирается на DOM, события и динамическую отрисовку через JavaScript. В SSR-сценариях значительная часть страницы формируется на сервере, поэтому интерактивная карта не может быть создана напрямую во время серверного рендеринга.

В экосистеме Google Maps Platform для таких задач используется подход со статическими картами, основанный на Static Maps API, который позволяет получать готовое изображение карты по HTTP-запросу без необходимости выполнения клиентского JavaScript.


Природа статических карт и их роль в SSR

Статическая карта представляет собой заранее отрендеренное изображение, формируемое на стороне сервиса картографии. В отличие от интерактивной карты, она не содержит:

  • обработчиков событий (click, drag, zoom),
  • динамических тайлов,
  • клиентского состояния карты,
  • WebGL или Canvas-рендеринга.

В SSR это превращает карту в обычный ресурс изображения (<img>), который может быть встроен непосредственно в HTML, сгенерированный сервером.

Ключевая особенность подхода заключается в том, что сервер формирует URL запроса к Static Maps API, а клиент получает уже готовый визуальный результат.


Архитектурная модель интеграции

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

  1. Сервер формирует HTML-страницу.

  2. На этапе рендеринга вычисляются параметры карты:

    • координаты центра,
    • масштаб (zoom),
    • набор маркеров,
    • стиль карты.
  3. Генерируется URL Static Maps API.

  4. URL вставляется в <img src="...">.

  5. Браузер загружает изображение как обычный ресурс.

Такой подход исключает зависимость от JavaScript на этапе первичной отрисовки страницы.


Формирование URL Static Maps API

Базовая структура запроса:

https://maps.googleapis.com/maps/api/staticmap

Параметры передаются через query string.

Основные параметры

center Определяет центр карты:

center=55.751244,37.618423

или текстовый адрес:

center=Moscow, Russia

zoom Масштаб карты:

zoom=12

Диапазон зависит от региона, но обычно 0–21.


size Размер изображения:

size=600x300

maptype Тип карты:

  • roadmap
  • satellite
  • terrain
  • hybrid

markers Добавление маркеров:

markers=color:red|55.751244,37.618423

key API-ключ:

key=YOUR_API_KEY

Пример серверной генерации URL

function buildStaticMapUrl({ lat, lng, zoom = 12 }) {
  const base = "https://maps.googleapis.com/maps/api/staticmap";

  const params = new URLSearchParams({
    center: `${lat},${lng}`,
    zoom: String(zoom),
    size: "600x300",
    maptype: "roadmap",
    markers: `color:red|${lat},${lng}`,
    key: process.env.GOOGLE_MAPS_API_KEY
  });

  return `${base}?${params.toString()}`;
}

Этот код выполняется на сервере (Node.js, NestJS, Next.js SSR и т.п.), не требуя подключения клиентской библиотеки.


SSR в Next.js и аналогичных фреймворках

В SSR-фреймворках статическая карта обычно формируется в getServerSideProps или серверных компонентах.

Пример логики:

export async function getServerSideProps() {
  const lat = 55.751244;
  const lng = 37.618423;

  const mapUrl = buildStaticMapUrl({ lat, lng });

  return {
    props: {
      mapUrl
    }
  };
}

В шаблоне:

<img src="{mapUrl}" alt="Map" />

Такой подход полностью исключает использование window, document и любых браузерных API.


Отличия Static Maps от Google Maps JavaScript API

Рендеринг

Static Maps:

  • сервер формирует изображение
  • результат — PNG/JPEG

JavaScript API:

  • клиентская отрисовка
  • WebGL/Canvas
  • интерактивность

Производительность

Static Maps:

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

JavaScript API:

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

Интерактивность

Static Maps:

  • отсутствует

JavaScript API:

  • полная интерактивность (zoom, pan, overlays)

SEO и SSR

Static Maps:

  • индексируется как изображение
  • не требует выполнения JS
  • стабильно отображается в SSR

JavaScript API:

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

Кэширование и CDN-стратегия

Статические карты идеально подходят для кэширования, поскольку URL полностью детерминирован.

Уровни кэширования:

  1. Браузерный кэш

    • стандартные HTTP cache headers
  2. CDN

    • Cloudflare, Fastly, AWS CloudFront
  3. SSR-кэш

    • Redis/Memcached для готовых HTML-фрагментов

Практика оптимизации

  • фиксировать параметры карты (не генерировать случайные значения)
  • избегать избыточного количества маркеров
  • группировать точки в кластеры до генерации URL
  • использовать одинаковые URL для одинаковых данных

Безопасность API-ключа

При использовании Google Maps Platform ключ API должен быть защищён:

Ограничения ключа:

  • HTTP referrer restriction (для браузера)
  • IP restriction (для SSR)
  • ограничение по API (только Static Maps API)
  • квоты на запросы

В SSR особенно важно ограничить ключ по IP сервера, чтобы предотвратить утечку и злоупотребление.


Работа с маркерами в SSR

Маркеры формируются на сервере как часть URL.

Один маркер

markers=color:red|55.751244,37.618423

Несколько маркеров

markers=color:blue|55.75,37.61|55.76,37.62

Стилизация маркеров

  • color
  • label (A-Z, 0-9)
  • icon (кастомная иконка по URL)

Динамическая генерация карт в SSR-потоке

SSR часто работает с данными из базы:

  • адреса пользователей
  • точки доставки
  • геолокации объектов

Типичный поток:

  1. SQL/NoSQL запрос
  2. получение координат
  3. формирование URL
  4. вставка в HTML

Ограничения Static Maps API

Несмотря на удобство, подход имеет ограничения:

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

Гибридный подход SSR + интерактивная карта

Часто используется комбинированная схема:

  • SSR: статическая карта как fallback
  • CSR: загрузка Google Maps JavaScript API после гидратации

Пример логики:

  • до загрузки JS → <img> со Static Maps
  • после загрузки → замена на интерактивную карту

Это позволяет:

  • ускорить First Contentful Paint
  • сохранить UX интерактивности
  • избежать пустых блоков на SSR-странице

Генерация стилевых параметров карты

Static Maps поддерживает ограниченные стили:

  • изменение цвета дорог
  • упрощение интерфейса
  • скрытие POI
  • изменение насыщенности

Пример:

style=feature:road|element:geometry|color:0x000000

В SSR такие стили формируются на сервере на основе темы приложения (light/dark mode).


Интеграция с бизнес-логикой SSR

В реальных приложениях статические карты часто связаны с:

  • страницами товаров (доставка)
  • карточками объектов недвижимости
  • каталогами компаний
  • логистическими маршрутами (упрощённо)

SSR позволяет заранее подготовить:

  • координаты
  • подписи
  • маркеры
  • масштаб

и встроить карту как часть HTML-ответа без дополнительных клиентских запросов.


Производительность SSR при большом количестве карт

Если страница содержит много карт:

  • увеличивается количество внешних HTTP-запросов
  • возрастает TTFB внешних ресурсов
  • увеличивается нагрузка на API квоты

Оптимизации:

  • объединение точек в одну карту
  • lazy loading изображений (loading="lazy")
  • использование placeholder
  • кэширование URL-результатов

Типовые ошибки интеграции

  • генерация URL на клиенте вместо сервера в SSR-сценарии
  • отсутствие ограничений API ключа
  • использование интерактивного API на сервере
  • отсутствие кэширования одинаковых карт
  • перегрузка карты слишком большим количеством маркеров