Breaking changes

Breaking changes в Kepler.gl представляют собой изменения в API, структуре конфигурации, состоянии карты и внутренних зависимостях, которые нарушают обратную совместимость между версиями. Такие изменения затрагивают интеграции, построенные на стабильных интерфейсах библиотеки, включая React-компоненты, Redux-слой, конфигурацию визуализаций и формат данных.


Архитектурная основа и точки возникновения несовместимостей

Kepler.gl построен как надстройка над экосистемой геовизуализации, включающей React, Redux и deck.gl. Любое изменение в одном из этих слоёв способно вызвать цепочку breaking changes:

  • обновления React могут менять жизненный цикл компонентов карты
  • изменения Redux-состояния влияют на сериализацию и восстановление карты
  • обновления deck.gl затрагивают рендеринг слоёв и шейдерную модель
  • модификации internal utils изменяют обработку данных и проекций

Особое значение имеет связка Kepler.gl ↔︎ deck.gl, поскольку слои визуализации напрямую зависят от структуры props и uniform-параметров WebGL.


Изменения структуры состояния карты (mapState)

Одним из наиболее чувствительных элементов является mapState, описывающий положение, масштаб и ориентацию карты.

Типовые breaking changes в этой области включают:

  • переименование полей (latitude, longitude сохраняются, но добавляются новые параметры камеры)
  • переход от плоской структуры к вложенной (camera state abstraction)
  • изменение диапазонов значений zoom
  • введение дополнительных параметров перспективы (pitch, bearing normalization)

Пример эволюции структуры:

// устаревший формат
mapState: {
  latitude: 55.75,
  longitude: 37.61,
  zoom: 10
}

// обновлённый формат
mapState: {
  latitude: 55.75,
  longitude: 37.61,
  zoom: 10,
  bearing: 0,
  pitch: 0,
  dragRotate: true
}

При миграции критично учитывать дефолтные значения, которые могут изменять визуальное поведение без явного изменения конфигурации.


Breaking changes в конфигурации слоёв (layers)

Слои в Kepler.gl являются основным механизмом визуализации данных. Любые изменения в их описании приводят к несовместимости сохранённых конфигураций.

Основные категории изменений:

Переименование типов слоёв

Некоторые версии изменяют идентификаторы слоёв или их внутренние ключи:

  • point → icon / pointLayer (в зависимости от версии)
  • line → path / arc
  • heatmap → heatmapLayer

Изменение схемы props слоя

// старый формат
layer: {
  type: 'point',
  config: {
    dataId: 'dataset_1',
    color: [255, 0, 0]
  }
}

// новый формат
layer: {
  type: 'point',
  config: {
    dataId: 'dataset_1',
    visualChannels: {
      colorField: null,
      colorScale: 'quantile'
    },
    color: [255, 0, 0]
  }
}

Добавление visualChannels является типичным примером breaking change, так как переносит логику визуального кодирования из плоских свойств в структурированную модель.


Изменения формата данных

Kepler.gl поддерживает несколько источников данных, включая GeoJSON, CSV и JSON-таблицы. Breaking changes часто затрагивают нормализацию данных:

GeoJSON обработка

  • изменение требований к CRS (Coordinate Reference System)
  • более строгая валидация координат
  • игнорирование некорректных geometry типов вместо fallback-поведения

Табличные данные

  • изменение требований к уникальности dataId
  • переход от implicit typing к explicit column mapping
  • изменение поведения null/undefined значений

Пример трансформации данных

// старый подход
data: {
  fields: ['lat', 'lng', 'value']
}

// новый подход
data: {
  fields: [
    { name: 'lat', type: 'real' },
    { name: 'lng', type: 'real' },
    { name: 'value', type: 'integer' }
  ]
}

Изменения Redux action API

Kepler.gl активно использует Redux actions для управления состоянием. Breaking changes часто проявляются в следующих формах:

  • переименование action types
  • изменение payload структуры
  • объединение нескольких actions в один
  • удаление legacy actions

Пример:

// устаревший action
dispatch(addDataToMap({ datasets, options }))

// обновлённый action
dispatch(addDataToMap({
  datasets,
  options,
  config: {
    centerMap: true,
    readOnly: false
  }
}))

Также наблюдается переход к более декларативному стилю управления состоянием, где actions описывают намерение, а не конкретную операцию.


Совместимость с deck.gl и WebGL слоем

Одним из наиболее критичных источников breaking changes являются обновления deck.gl:

  • изменение модели Layer props
  • обновление Attribute Manager
  • переход на новые версии WebGL2 API
  • изменение поведения инстансинга

Пример влияния:

  • старые кастомные слои перестают корректно рендериться
  • шейдерные uniforms требуют переопределения
  • меняется порядок вычисления координат

Изменения сериализации конфигурации (visState)

visState хранит описание всех визуальных компонентов карты: слои, фильтры, взаимодействия.

Breaking changes в этой области включают:

  • изменение структуры filters
  • добавление временных диапазонов как обязательных полей
  • изменение формата interactionConfig
  • перенос части логики в config.visState

Пример:

// старый формат фильтра
filters: [
  {
    name: 'timestamp',
    value: [0, 100]
  }
]

// новый формат
filters: [
  {
    id: 'timestamp_filter',
    dataId: 'dataset_1',
    name: 'timestamp',
    value: [0, 100],
    type: 'timeRange'
  }
]

Переходы между версиями и стратегия миграции

Миграции между версиями Kepler.gl требуют последовательного анализа изменений в трёх слоях:

  1. состояние Redux (mapState, visState)
  2. конфигурация слоёв (layers)
  3. формат данных (datasets)

Типовой подход включает:

  • нормализацию старых конфигураций через адаптер
  • создание промежуточного слоя трансформации
  • постепенный отказ от legacy полей

Пример адаптера:

function migrateConfig(oldConfig) {
  return {
    ...oldConfig,
    visState: normalizeVisState(oldConfig.visState),
    mapState: normalizeMapState(oldConfig.mapState)
  };
}

Изменения в расширяемости (plugins и custom layers)

Kepler.gl поддерживает расширение через кастомные слои и плагины. Breaking changes часто затрагивают:

  • интерфейс регистрации layer factory
  • сигнатуры методов render / update
  • доступ к context и theme
  • порядок инициализации plugin middleware

Типичный пример:

// устаревший plugin API
export function myLayer() {
  return {
    type: 'custom',
    render: () => {}
  };
}

// обновлённый API
export function myLayerFactory(deps) {
  return {
    id: 'custom-layer',
    renderLayer: (props) => {}
  };
}

Частые проблемы при обновлениях

При переходе между версиями наиболее часто возникают следующие классы ошибок:

  • карта загружается без слоёв из-за несовпадения schema
  • фильтры перестают применяться из-за изменения id
  • данные отображаются некорректно из-за изменения типов колонок
  • кастомные слои не регистрируются из-за изменения API
  • потеря состояния камеры при изменении mapState

Деградации поведения при частичной миграции

Несовпадение версий разных частей конфигурации приводит к частичной деградации:

  • корректный mapState при некорректном visState
  • отображение слоёв без интерактивности
  • фильтрация без обновления UI
  • расхождение между сохранённой и восстановленной картой

Такие эффекты возникают при смешивании конфигураций разных версий без полной нормализации.


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

В ряде версий изменяется модель работы с временными данными:

  • переход от числовых timestamp к Date-совместимым форматам
  • изменение интерпретации time slider
  • обновление интерполяции между состояниями

Пример изменения фильтра времени:

// старый формат
value: [1514764800000, 1546300800000]

// новый формат
value: ['2018-01-01', '2019-01-01']

Итоговые закономерности эволюции API

Breaking changes в Kepler.gl повторяют несколько устойчивых паттернов:

  • переход от плоских структур к вложенным конфигурациям
  • усиление типизации данных
  • вынос визуальных параметров в отдельные доменные блоки
  • унификация layer API под deck.gl
  • повышение строгости валидации данных