Конфликты зависимостей

Экосистема Kepler.gl построена вокруг связки React, Redux и визуального движка deck.gl, что автоматически создаёт чувствительность к версиям зависимостей. Любое расхождение в minor/major версиях приводит к ошибкам сборки, некорректному рендерингу слоёв или падению приложения на этапе инициализации.

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

  • React и React DOM
  • Redux и middleware-стек
  • deck.gl, luma.gl и связанные пакеты
  • mapbox-gl
  • peerDependencies в npm ≥ 7
  • дублирование пакетов в дереве зависимостей

Конфликты React-экосистемы

Kepler.gl критично зависит от согласованной версии React. Основная проблема возникает при наличии нескольких копий React в дереве зависимостей.

Типичный сценарий конфликта:

  • основной проект использует React 18
  • одна из зависимостей Kepler.gl подтягивает React 17 как peer/optional dependency
  • итог: нарушение правил хуков

Ошибка проявляется в виде:

  • Invalid hook call
  • Hooks can only be called inside of the body of a function component

Причина — дублирование React-рантайма, когда React Context становится несовместимым между экземплярами.


Дублирование React в node_modules

Даже при одинаковых версиях React возможна ситуация, когда:

  • один пакет резолвит React из корня
  • другой получает локальную копию

Это приводит к двум независимым состояниям React reconciler.

Особенно часто проявляется при:

  • монорепозиториях
  • использовании npm link
  • смешении npm и yarn install

deck.gl и связка визуализации

Kepler.gl тесно связан с deck.gl, который в свою очередь зависит от luma.gl. Эти пакеты развиваются синхронно, и несовпадение версий вызывает каскадные ошибки.

Типичные проблемы:

  • несовместимость Layer API
  • изменения в ShaderModule интерфейсах
  • различия в WebGL context management

При несовпадении версий возможны:

  • пустая карта без слоёв
  • ошибки WebGL context lost
  • некорректная отрисовка геометрии

Ключевой принцип: deck.gl и kepler.gl должны быть взяты из совместимого диапазона версий, а не устанавливаться независимо.


mapbox-gl и несовместимость рендерера

Kepler.gl использует Mapbox GL как базовый картографический движок. Конфликты возникают при переходе между major-версиями mapbox-gl.

Основные источники проблем:

  • изменение API Style Specification
  • переход на Mapbox GL JS v2+
  • конфликт WebGL context sharing
  • несовместимость с deck.gl overlays

Типичный симптом:

  • карта загружается, но тайлы не отображаются
  • ошибки вида Expression is not allowed in style spec
  • некорректное позиционирование слоёв

PeerDependencies и npm 7+

С появлением npm 7 поведение установки peerDependencies стало строгим, что резко увеличило число конфликтов при установке Kepler.gl.

Сценарий:

  • npm автоматически устанавливает несовместимые peerDependencies
  • возникает конфликт версий React, Redux или deck.gl
  • сборка падает с ERESOLVE

Типичная ошибка:

  • ERESOLVE unable to resolve dependency tree

В старых проектах на npm 6 проблема могла маскироваться, но в новых версиях становится явной.


Дублирование Redux и middleware

Kepler.gl использует сложный Redux store с middleware для асинхронных операций и взаимодействия с визуализацией.

Конфликты возникают при:

  • разных версиях redux в зависимостях
  • подключении redux-thunk / redux-saga с несовместимыми версиями
  • наличии нескольких store-инстансов

Последствия:

  • состояние визуализации не синхронизируется
  • панель фильтров не обновляется
  • действия dispatch игнорируются

Механизмы разрешения конфликтов

Yarn resolutions

Наиболее прямой способ принудительного выравнивания версий:

{
  "resolutions": {
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "deck.gl": "8.9.0"
  }
}

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


npm overrides

Аналогичный механизм в npm:

{
  "overrides": {
    "react": "18.2.0",
    "react-dom": "18.2.0"
  }
}

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


pnpm и изоляция зависимостей

pnpm уменьшает вероятность конфликтов за счёт строгой изоляции:

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

Однако при Kepler.gl важно следить за hoisting поведением:

  • неправильный hoist может снова создать дубль React
  • требуется настройка public-hoist-pattern

Webpack aliasing как способ фиксации

Если конфликт не удаётся устранить на уровне package manager, используется aliasing:

resolve: {
  alias: {
    react: path.resolve("./node_modules/react"),
    "react-dom": path.resolve("./node_modules/react-dom")
  }
}

Это принудительно заставляет сборщик использовать единственный экземпляр React.


Проверка дерева зависимостей

Для диагностики конфликтов используются стандартные инструменты:

npm

npm ls react
npm ls deck.gl

yarn

yarn why react
yarn why deck.gl

Анализ показывает:

  • наличие дубликатов
  • пути резолва пакетов
  • конфликтующие версии

Совместимость версий Kepler.gl

Kepler.gl не гарантирует backward compatibility между major-версиями, поэтому ключевым фактором становится фиксация связанного набора:

  • kepler.gl
  • deck.gl
  • react-map-gl
  • mapbox-gl
  • redux

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


Проблемы сборщиков и SSR

В проектах с server-side rendering конфликты зависимостей усиливаются:

  • deck.gl использует WebGL, недоступный на сервере
  • mapbox-gl требует window/document
  • React hydration может конфликтовать при разных сборках клиента и сервера

Типичные решения:

  • динамический import компонентов Kepler.gl
  • отключение SSR для map-related модулей
  • условная инициализация WebGL контекста

Локализация и контроль версий в монорепозиториях

В монорепозиториях основной источник конфликтов — неявное поднятие зависимостей (hoisting).

Рекомендуемые подходы:

  • единый root package.json для React и Redux
  • фиксация версий через lockfile
  • запрет локальных установок React в пакетах workspace
  • централизованный контроль deck.gl

Особое внимание требуется при смешении UI-пакетов и data-слоёв, где Kepler.gl может быть подключён как зависимость в нескольких местах одновременно.