[Перевод] Visx — коллекция графических примитивов для React-приложений, созданная в Airbnb
После 3 лет разработки и 2,5 лет использования в продакшн-проектах Airbnb, после переписывания кода на TypeScript, мы рады представить вам официальный релиз коллекции графических примитивов visx 1.0 (раньше она называлась vx). Вот — страница проекта на GitHub. Документацию и примеры можно найти на airbnb.io.
Мы поставили себе цель, которая заключалась в том, чтобы унифицировать стек технологий визуализации данных, применяемый во всех проектах Airbnb. В ходе движения к этой цели мы создали новый проект, в котором объединена мощь D3 и удобство React. Среди сильных сторон visx мы можем отметить следующие:
- Использование коллекции способствует созданию бандлов приложений маленького размера. Дело в том, что visx разбита на множество пакетов. Поэтому при её использовании в некоем проекте можно взять из неё лишь то, что нужно.
- Коллекция спроектирована так, чтобы не навязывать программистам некие предопределённые схемы работы. Используя visx, разработчик может использовать собственную систему управления состоянием приложения, свою библиотеку анимации или подходящее ему CSS-in-JS-решение. Высока вероятность того, что при создании вашего React-приложения уже приняты решения о том, как в нём выполняются анимации, о том, какой подход используется для работы с темами, о том, как стилизуются элементы. Visx, в этом плане, ничего нового в приложения не добавляет. Библиотека интегрируется со всем тем, что уже есть в проект.
- Это — не коллекция элементов, «заточенная» под создание графиков. Если вы будете пользоваться визуализационными примитивами для создания графиков, то вы, в итоге, создадите собственную библиотеку, решающую эту задачу. Причём, это будет библиотека, оптимизированная под ваши нужды. Она будет находиться под вашим полным контролем.
Самая важная сильная сторона visx заключается в том, что это, в сущности, обычный набор React-компонентов. Если вы знаете о том, как работать с библиотекой React — это значит, что вы сможете использовать visx для создания визуализаций. Тут используются стандартные API и знакомые React-разработчикам паттерны. В любом React-проекте visx должна чувствовать себя как дома. Нам очень интересно взглянуть на то, что вы создадите с помощью visx!
Задача: визуализация данных во фронтенд-разработке
В визуализации данных нуждаются специалисты из самых разных сфер. Из-за этого возникает необходимость в существовании фреймворков для создания графических элементов. Таких фреймворков, которые способны решить задачи этих людей. Таких, которые этим людям реально освоить.
Одна из групп подобных специалистов — это фронтенд-разработчики, которым постоянно приходится создавать визуализации данных для веб-проектов. Существует огромное количество замечательных библиотек и фреймворков для создания веб-графики. От D3, Highcharts, Plotly, Echarts, Victory, G2, Recharts, react-vis, vega, vega-lite, до Semiotic и других подобных проектов. Но, несмотря на такое разнообразие, мы, проанализировав более десятка существующих библиотек, рассматривая возможность их использования в Airbnb, выяснили, что большинство из них имеют недостатки как минимум в одной из трёх областей, важных для наших фронтенд-разработчиков:
- Возможность быстрого изучения инструмента (как долго нужно изучать инструмент для того чтобы создавать и поддерживать визуализации?). Большинство фронтенд-программистов не являются экспертами в области визуализации. В крупной организации требуются серьёзные затраты времени и денег на переход к использованию императивного API D3 или на изучение особой грамматики vega. В идеале программисты должны иметь возможность изучить библиотеку для визуализации данных так же быстро, как они изучают другие фронтенд-пакеты.
- Выразительность (реально ли с помощью выбранного инструмента создать почти всё, что можно себе представить?). Каким должен быть фреймворк, который можно применять в масштабах большой компании в качестве стандартного инструмента для визуализации данных? Этот фреймворк должен поддерживать и создание простых диаграмм (скажем — для airbnb.com), и разработку сложных визуализаций для внутренних проектов компании. Должны ли особенности библиотеки для разработки диаграмм ограничивать возможности разработчиков по визуализации данных? Мы так не думаем.
- Производительность. Фронтенд-разработчики, специалисты, которые создают веб-приложения, уходящие в продакшн, вроде airbnb.com, должны иметь возможность оптимизировать производительность проектов и размеры их бандлов. В результате оказывается, что, например, универсальный фреймворк для построения диаграмм, содержащий встроенные анимации, встроенную систему стилизации и механизмы обработки особых событий может для целей конкретного проекта не подойти и способен ухудшить ситуацию с размером бандла проекта.
Отмечено, что часто наблюдается прямая связь между выразительностью инструментов для визуализации данных и возможностью их быстрого изучения. Чем лучше одна из этих характеристик, тем хуже может быть другая. Всё это подвело нас к вопросу о том, как создать библиотеку, которую можно быстро изучить, библиотеку, являющуюся достаточно выразительной, и при этом — ещё и высокопроизводительную. Ответ на этот вопрос состоит из одного слова: «React».
Решение: низкоуровневые визуальные примитивы, основанные на React
В последние годы библиотека React стала мейнстримом веб-разработки. Отчасти это так из-за того, что она обладает декларативными API, способствующими написанию чистого читабельного кода, который легко поддерживать. Эта библиотека знакома множеству фронтенд-разработчиков, существует много материалов, посвящённых оптимизации производительности React-приложений. Мы положили в основу проекта React и экосистему этой библиотеки, а значит — сделали его лёгким в изучении и производительным. Реализация в нём низкоуровневого модульного API стала залогом его выразительности.
Когда мы рассказываем о таком видении этого проекта, нам обычно задают два вопроса.
Вот первый: «Почему бы просто не использовать в React-приложениях D3 — весьма выразительную библиотеку?».
Дело в том, что можно так и сделать. Но так как и D3 и React стремятся единолично управлять DOM, мы обнаружили, что лучше всего, когда D3 используется исключительно для проведения вычислений, а React — для работы с DOM. Иначе две ментальных модели, конкурирующие за обновление DOM, открывают двери для проникновения в проект ошибок. Но использование D3 только для проведения вычислений означает, что большим куском функционала этой библиотеки (тем, что имеет отношение к DOM) пользоваться будет нельзя. Речь идёт о selection.join, zoom, drag, brush и о transitions. Кроме того, как уже было сказано, для освоения D3 нужно определённое время. А нам хотелось бы, чтобы, занимаясь визуализацией данных, разработчики чувствовали бы себя так, будто пишут нативный React-код, в котором используются стандартные API и знакомые паттерны.
Вот второй вопрос: «Почему бы просто не использовать одну из множества библиотек для визуализации, созданных для React?».
Наше исследование (его результаты представлены на следующем рисунке) показало, что существующие React-библиотеки для визуализации данных часто представляют собой высокоуровневые абстракции и оптимизированы с прицелом на простоту их использования (то есть — ориентированы на сокращение объёма кода, необходимого для их применения). Делается это ценой их выразительности. Ни одна из них не предлагает разработчику выразительности примитивов D3, многие не позволяют выполнять оптимизацию, нужную нам для продакшн-проектов, так как вычисления, анимации, управление состоянием, стили и рендеринг тесно связаны друг с другом.
Большинство библиотек для визуализации данных в веб-проектах оптимизированы в расчёте на простоту их использования, что может ограничить выразительность того, что можно с их помощью создать. Библиотека visx уникальна тем, что поддерживает выразительные примитивы для визуализации данных в React-приложениях
Анализируя пространство задачи, представленное на предыдущем рисунке, можно чётко увидеть возможность для благополучного развития React-библиотеки, отличающейся высоким уровнем выразительности. Создавая низкоуровневые визуализационные примитивы, изначально проектируемые с учётом использования в них обычных для React API, мы надеялись, что сможем создать библиотеку, которую легко будет изучать, которая будет отличаться выразительностью и высокой производительностью. Такая библиотека, как мы полагали, способна пригодиться любому фронтенд-разработчику. Так и родился проект visx.
Подробности о visx
Коллекция компонентов visx (ранее известная как vx) скрывает в своём названии слова «visualization components». Она состоит из более чем 30 отдельных пакетов, содержащих React-примитивы для визуализации данных, разделённые на несколько категорий (смотрите следующий рисунок). Тому, кто использует эти примитивы, не навязывается некая схема управления состоянием приложения. Разработчик может сам выбирать подход к анимации элементов и к их стилизации. Всё это значит, что примитивы visx могут быть интегрированы в любую кодовую базу, основанную на React. А то, что при создании visx был сделан упор на модульность (это роднит visx с D3) позволяет создавать бандлы приложений компактного размера, включая в их состав лишь то, что нужно для реализации собственной библиотеки для визуализации данных, предназначенной для многократного использования, или то, что необходимо для формирования какого-нибудь уникального графика, существующего в единственном экземпляре.
Visx — это модульная коллекция, состоящая из более чем 30 пакетов, решающих распространённые задачи из области визуализации данных в React-приложениях
Вопросы и ответы
▍Как в visx используется D3?
Некоторые пакеты, входящие в состав visx, используют D3 для выполнения различных вычислений, например, связанных с размещением элементов на страницах. Они функционально повторяют используемые в них пакеты D3, оснащая их декларативными API React. Среди примеров таких пакетов — @visx/axis, @visx/geo, @visx/hierarchy и @visx/shape. Другие пакеты заменяют функционал D3, связанный с управлением DOM, и дают разработчику React-примитивы, направленные на организацию взаимодействия с элементами. Это, например, @visx/brush, @visx/drag и @visx/zoom.
▍Что такого умеет visx, чего не умеет D3?
Многие пакеты совершенно не связаны с D3, они абстрагируют решения часто встречающихся задач, с которыми мы столкнулись, создавая в React визуализации дизайнерских макетов, воспроизводящие макеты с точностью до пикселя. Многие из этих средств абстрагируют и упрощают решение сложных задач по измерению объектов и упрощают API SVG. Вот несколько примеров.
@visx/tooltip
Вот интерактивный пример.
Всплывающие подсказки
Всплывающие подсказки — это элемент, который часто используется в веб-проектах. Но реализация всех микровзаимодействий с такими элементами представляет собой непростую задачу. Пакет @visx/tooltip абстрагирует управление состоянием всплывающей подсказки. Он помогает управлять её содержимым, её координатами, её показом и скрытием. Делается это с использованием хуков React (useTooltip) и с использованием компонента высшего порядка (withTooltip). Использование пакета @visx/tooltip, кроме того, упрощает решение задач, связанных с рендерингом всплывающих подсказок, таких, как автоматическое позиционирование (в результате подсказка не обрезается своим контейнером), и таких, как опциональный вывод внутри портала для устранения проблем, связанных с контекстном наложения
@visx/text
Здесь можно найти интерактивный пример.
Работа с текстом
В SVG 1.1. нет возможностей по работе с многострочным текстом, подобных тем, что есть в HTML, где, например, можно легко, средствами CSS, реализовать многострочное представление длинных текстов. Реализация подобных механизмов средствами React (или даже на чистом JavaScript) обычно требует рендеринга невидимых элементов DOM, используемых для измерения размеров текстов и для нахождения параметров разбиения текстов на строки. Пакет @visx/text абстрагирует решение всех этих задач и упрощает поддержку длинных текстов в визуализациях.
@visx/responsive
Вот интерактивный пример.
Отзывчивое веб-приложение
Отзывчивые веб-приложения легко создавать средствами HTML. Если же диаграммы создают, опираясь на SVG-графику и на возможности элемента canvas, то для придания им отзывчивости нужно проводить измерения пиксельной точности, что в React сделать не так уж и просто. Пакет @visx/responsive даёт в распоряжение разработчика множество вспомогательных инструментов, которые упрощают получение сведений о размерах элементов в пикселях, что позволяет с удобством создавать отзывчивые диаграммы.
@visx/gradient, @visx/pattern
Здесь находится интерактивный пример.
Градиенты и шаблоны
Цветовые градиенты и заполнение элементов по шаблону значительно расширяют возможности тех, кто отвечает за дизайн диаграмм. Эти графические эффекты позволяют создавать привлекательные, выделяющиеся на общем фоне изображения. Но описание подобных изображений средствами SVG требует написания большого объёма кода и может оказаться непростой задачей. Пакеты @visx/gradient и @visx/pattern сильно упрощают синтаксис объявления соответствующих стилей, что позволяет всем желающим создавать симпатичные диаграммы.
▍Что можно создать с использованием visx?
Мы используем visx последние 2,5 года, применяя эту коллекцию элементов в десятках внутренних инструментов для работы с данными и на airbnb.com.
Визуализации, созданные с помощью visx
На предыдущем рисунке приведены примеры того, что мы создали с использованием visx. Это, если идти по часовой стрелке, начиная с верхнего левого угла, следующие проекты: диаграмма Гантта с зависимостями, круговая организационная диаграмма, радиальная диаграмма, отчёт по бизнес-показателям, обзор взаимодействия сервисов.
Мы, кроме того, задействовали visx при создании высокоуровневой библиотеки для создания диаграмм, предназначенной для многократного использования. Это позволило нам сократить объём шаблонного кода при формировании простых графических элементов.
Visx — это коллекция низкоуровневых элементов. Она рассчитана на то, что на её основе будут создавать системы более высокого уровня. Её стоит использовать для создания собственных высокоуровневых библиотек и для создания особых визуализаций для веб-приложений
▍Visx выглядит интересно, но как быть, если мне очень нравится D3?
Нам тоже очень нравится D3!
▍Как развивается visx?
За 3 года работы над visx мы развивали эту коллекцию примитивов по трём следующим направлениям:
- Функционал. По мере того как мы встраивали библиотеки, входящие в состав visx, в веб-приложения Airbnb, мы сталкивались с некоторыми ограничениями (например — с отсутствием поддержки взаимодействий с пользователем, с тем, что эти библиотеки не поддерживают некоторые типы диаграмм или макетов страниц) или обнаруживали, что нам приходится постоянно повторять реализации одних и тех же элементов (подписей на диаграммах, всплывающих подсказок). Со временем мы добавили в пакеты коллекции те возможности, которых нам не хватало, или, основываясь на том, что мы делали в проектах, создали совершенно новые пакеты.
- Документация. Более трёх десятков пакетов, входящих в visx, не принесут особой пользы в том случае, если программисты не будут знать о том, как ими пользоваться. Главнейшей потребностью сообщества, сложившегося вокруг vx, была качественная документация. Недавно мы расширили документацию по всем пакетам visx, оснастили её ссылками на множество примеров в стиле blocks.org, создали интерактивные примеры на CodeSandbox, с которыми удобно экспериментировать, переделали дизайн сайта проекта, ориентируясь на ребрендинг visx.
- Качество. Изначально коллекция visx была JavaScript-проектом, но её полностью переписали на TypeScript. Это позволило значительно улучшить типобезопасность при работе с ней и помогло повысить удобство её использования разработчиками. Теперь TypeScript — это официальный язык фронтенд-разработки в Airbnb. Мы, для упрощения перевода наших проектов на TypeScript, создали особый инструмент — ts-migrate. Мы, кроме того, недавно улучшили покрытие кода visx модульными тестами. А в ближайшем будущем мы, с использованием Happo, собираемся внедрить тестирование visx, основанное на снимках экрана.
В документации к visx используются примеры в стиле blocks.org, с которыми можно экспериментировать на платформе CodeSandbox. Все примеры тесно связаны с соответствующими пакетами коллекции
Пользовались ли вы visx?