Абсолютно стандартное начало: в Figma размещался набор из примерно тысячи иконок, которые успешно перенесли в проект. Все собрали, потестили и зарелизили. Про автоматизацию никто не думал, поскольку задача казалась «одноразовой». Ну а в случае последующих обновлений или дополнений каких-то элементов ручной труд должен был занять несколько минут. Что тут может пойти не так?
Далее рассказ про знакомый всем «человеческий фактор», плюс краткий гайд по автоматизированному экспорту картинок из Figma в рабочий проект.
Итак, дано: приложения под iOS и Android с большим набором иконок, который постоянно обновляется и дополняется стараниями нашей команды дизайнеров. Выглядел этот набор примерно так:
Частота внесения изменений небольшая — примерно пару раз в месяц что-то там менялось. Вроде бы ничего особенного, но в какой-то момент проблемы стали накапливаться.
Проблема №1 — расплодившиеся дубли
По мере расширения набора функций у приложения требовались новые иконки. Разработчик, который реализовывал ту или иную фичу, в какой-то момент обнаруживал, что нужные иконки в интерфейсе не появлялись. Он залезал в Фигму, пролистывал таблицу, находил там нужную иконку, копировал её себе, затем переводил из формата SVG в VectorDrawable, задавал имя файла и закидывал в проект.
В этот момент другой разработчик, реализующий другую функцию, также обнаруживал отсутствие иконки и повторял все вышеописанные действия. Разумеется, есть прописанные правила именования файлов, которым все следуют, но, когда у тебя их тысяча, да ещё в разных форматах и размерах, периодически что-то идёт не так.
Проблема №2 — иконки оказывались не того формата и размера
В Figma иконки хранились как компоненты. Но обязательно находился тот, кто по ошибке раскрывал компонент и обнаруживал внутри поле Icon. Затем загружал себе этот самый Icon, который по размеру немного отличался от размера компонента. Если не присматриваться, на первый взгляд всё было нормально. Однако в отдельных местах интерфейс начинал «плыть». И это не всегда удавалось заметить сразу.
Проблема №3 — когда начинают фиксить в коде
Раз интерфейс «поплыл», а иконка была загружена правильная, и в других местах с ней все было как бы нормально, разработчик принимал решение поджать её в коде в конкретном месте, где возникала проблема.
Это копилось ровно до того момента, пока не начиналось ревью. А на нём всплывало всё и сразу. И кто-то потом сидел и распутывал весь клубок, удивляясь, как же коллеги могли нагородить такого. Поэтому настало время всё сделать по-человечески — автоматизировать.
От полного хаоса к нажатию одной кнопки
Автоматизация должна была решить сразу несколько задач: создать единую систему имён файлов, выгружать и конвертировать в нужный формат полный набор иконок (VectorDrawable для Android и PDF для iOS), затем закидывать их в проект, заменяя существующие и удаляя ненужные. Осталось только написать нужный скрипт.
Для начала предстояло выбрать язык. После обсуждения доступного инструментария остановились на следующих вариантах:
- написать скрипт на Bash;
- каждая команда пишет скрипт для своей ОС;
- кроссплатформенное решение на Kotlin.
Первый вариант отбросили, поскольку Bash это дополнительный язык, который нужно знать, чтобы поддерживать решение. Писать свой скрипт под каждую платформу — это умножать разработку на два. А вот вариант на Kotlin нам показался перспективным, поскольку Kotlin — родной язык для Android-разработчиков, вдобавок он имеет много сходств со Swift, который используют iOS-разработчики.
Так сложилось, что мой опыт разработки был связан с UI-kit, поэтому задачка попала ко мне.
Было два варианта экспорта, и я выбрал не тот
Потратив немного времени на изучения Figma API, кристаллизовались два пути, которыми можно было экспортировать данные для дальнейшей обработки. Первый — выгрузить всю иерархию элементов файла, распарсить и получить нужные данные. Второй — работать с компонентами из файла напрямую.
Изначально показалось, что первый способ даст на выходе больше информации, с которой будет удобнее работать. Я создал скрипт, который отлично проработал несколько дней. За это время я успел собрать немного лучей славы от благодарных коллег, но потом случилось то, что когда-то должно было произойти. Дизайнеры в макете Figma в одном месте перегруппировали иконки и что-то переименовали. После чего скрипт перестал нормально работать. По факту изменилась структура данных, а за ней и иерархия файла. Пришлось идти и обновлять скрипт выгрузки.
Решить данную проблему можно двумя способами. Договориться с дизайнерами, чтобы они ничего не меняли в структуре, хранили иконки в нужной иерархии и не нарушали её. Или выгружать иконки как компоненты.
После краткого общения с дизайнерами число вариантов сократилось до одного — выгрузка компонентов. Увы, контроль структуры оказался более сложной задачей.
В итоге схема стала такой: получаем список компонентов, берём их айдишники, затем получаем список файлов для скачивания и выгружаем, а с помощью системы контроля версий студия подсвечивает нам новые, удаленные и изменившиеся. Далее преобразуем в нужный формат и загружаем в проект.
Краткая пошаговая инструкция по выгрузке данных
У Figma есть подробное описание API. Но для более быстрого ознакомления с ним покажу в общих чертах, как выглядит процесс настройки экспорта.
1. Первым шагом нужно сгенерить access token на сайте figma api. Для этого надо перейти на figma.com/developers/api#authentication и нажать Get personal access token
2. Узнать file id нашего комплекта изображений. Его можно взять из адреса страницы
3. Чтобы получить компоненты, необходимо выполнить запрос GET/v1/files/:file_key/components
, где :file_key
— ключ из адреса веб-страницы нашей библиотеки изображений в Figma.
В ответ на запрос мы получим данные в следующем формате:
{
"status": Number,
"error": Boolean,
"meta": {
"components": [
{
"key": String,
"file_key": String,
"node_id": String,
"thumbnail_url": String,
"name": String,
"description": String,
"updated_at": String,
"created_at": String,
"user": User,
"containing_frame": FrameInfo,
},
...
],
},
}
Здесь нас интересуют поля в meta.components:
node_id
— это id компонента
name
— название компонента
containing_frame
— информацию о фрейме, в котором лежит иконка
4. Из всей этой информации мы забираем название фрейма. Затем формируем следующий запрос:
"https://api.figma.com/v1/images/$fileId?ids=$keys&format=$format&use_absolute_bounds=true
"
Где fileId
— тот же ключ библиотеки с иконками
keys
— наши node_id, необходимые для выгрузки
format
– тут можно указать svg, pdf, jpg или png
use_absolute_bounds
— этот флаг нужен для того, чтобы Figma не обрезала заложенные дизайнерами отступы
В ответ получаем пару «ключ — значение», где ключ — это ID компонента, а значением будет URL самой картинки для выгрузки. Затем по полученным URL выгружаем наши изображения.
Конвертацию из svg в VectorDrawable выполняем с помощью com.android.ide.common.vectordrawable.Svg2Vector из библиотеки com.android.tools.sdk-common. Пример вызова метода конвертации выглядит так: Svg2Vector.parseSvgToXml(Path, OutputStream)
. Для iOS никаких дополнительных действий делать не нужно, поскольку данные выгружаются в формате pdf, с которыми разработчики работают напрямую.
Что получили в итоге
Во-первых, понимание того, что об автоматизации лучше задумываться как можно раньше и закладывать на неё время. В нашем случае, с учетом изучения API и первоначального прохождения по ложному пути, ушло около пяти рабочих дней. Возможно, оно ещё не компенсировалось экономией времени на разборе хаоса и ручной выгрузке, однако мы получили полный порядок в данных и отсутствие необходимости постоянного выяснения что и почему отображается не так.
Во-вторых, избавление от рутины, которая нагружает голову и не даёт сосредоточиться на более важных вещах. Ведь нажать одну кнопку и через 30 секунд продолжить текущую работу — это не то же самое, что открыть несколько приложений, внимательно смотреть что и откуда брать, во что конвертировать и куда потом положить. Подобные рутинные операции частенько выбивают из потока, что по факту отнимает ещё время, требующееся для возвращения к текущей задаче.
Так что, если у вас возникнет необходимость в экспорте из Figma, можно смело браться за автоматизацию. Ничего сложного в ней нет. Важно лишь помнить, что выгружая иерархию файла для дальнейшей обработки, придётся следить за изначальной целостностью структуры. Или сразу переходить к варианту покомпонентного экспорта.