1. Введение
По мере продвижения проекта процесс завершения одного экрана часто разделяется на большее количество задач, чем ожидалось.
В проектах я отвечаю за реализацию UI-элементов, таких как разметка экранов, стилизация и взаимодействия. Ранее репозитории для публикации и разработки были физически разделены, поэтому я работал только в репозитории для публикации. После завершения разметки и стилей разработчик переносил их в репозиторий для разработки и добавлял логику и API.
Однако в этом проекте структура была иной. Процесс изменился: специалист по публикации работал непосредственно в репозитории для разработки, создавая отдельную ветку и работая параллельно с разработчиками. Использование одного репозитория и общей кодовой базы давало определённые преимущества, но создавало и новые трудности. Несмотря на то что мы работали над одним и тем же экраном в одном репозитории, было сложно увидеть фактически завершённый экран целиком, пока изменения из веток друг друга не были объединены.
При работе в ветке публикации API мог быть ещё не готов, а разрабатываемая в другой ветке логика управления состоянием могла оставаться незавершённой.
В этой статье я хочу обобщить свой опыт применения Storybook для более независимой разработки и проверки UI в среде, где публикация и разработка выполняются раздельно в разных ветках одного репозитория, а также описать проблемы, с которыми я столкнулся во время фактической реализации.
2. Формулировка проблемы: что необходимо для проверки одного экрана
Поскольку работа была разделена между ветками одного репозитория, возникала раздражающая ситуация: казалось, что «мы должны увидеть результат сразу после объединения, но на деле это не так». Пока разметка в моей ветке и логика в ветке разработки не были объединены, не существовало практического способа проверить завершённый экран целиком.
В таком состоянии для проверки конкретного экрана в реальной среде требовалось выполнить несколько условий.
Во-первых, нужно было запустить среду разработки, содержащую соответствующий экран, а в некоторых случаях — одновременно запустить несколько приложений или серверов разработки. Кроме того, для экранов, требующих авторизации или ответов API, нужно было подготовить реальные данные, чтобы создать нужное состояние.
Однако при работе в ещё не объединённой ветке эти условия не всегда были выполнены.
Например, спецификация API могла быть определена, хотя фактический сервер ещё не был реализован, или было сложно намеренно создать данные для конкретного состояния. Пустые списки, условия отображения определённых кнопок, состояния завершённых заявок и состояния ошибок не всегда было легко проверить, просто запустив реальный сервис.
В результате даже для проверки простого состояния UI приходилось запускать всю среду разработки, переходить на нужный экран, а затем создавать конкретные условия.
Этот процесс создавал следующие проблемы.
- Работа по публикации зависела от готовности среды разработки.
- Было сложно многократно воспроизводить определённые состояния UI.
- Каждое изменение данных API также влияло на процесс проверки экрана.
- Чтобы проверить состояние экрана, каждый раз приходилось ждать подготовки данных или среды командой разработки либо запрашивать их.
В частности, работа над UI требует проверки не только обычных состояний, но и различных ситуаций, таких как пустые, исключительные состояния и состояния загрузки. Однако в реальной среде разработки намеренное создание этих состояний каждый раз требовало дополнительного времени.
Поэтому нам был нужен не просто способ отдельно отображать экраны, а среда, в которой состояния конкретных компонентов и экранов можно было бы стабильно воспроизводить в любое время.
3. Решение: создание независимой среды разработки UI с помощью Storybook
Чтобы решить эту проблему, я применил Storybook.
Основной целью была возможность немедленно проверять состояния экранов на локальной машине, не запрашивая данные или среду у команды разработки, даже когда API ещё не был готов — или, в крайнем случае, когда в среде разработки было вообще невозможно войти в систему и открыть экран.
Storybook — это инструмент, который позволяет отображать и проверять компоненты независимо, отдельно от общей среды приложения. Однако я стремился использовать его не просто для просмотра списка компонентов, а для создания среды, максимально похожей на фактическую среду разработки UI проекта.
Для этого я настроил его на основе следующих основных принципов.
- Использовать в Storybook ту же конфигурацию Vite, что и в фактическом проекте
- Воспроизвести среду Provider, используемую фактическим приложением
- Обеспечить возможность немедленной проверки состояний экранов на локальной машине без запросов, даже если API или среда авторизации команды разработки ещё не готовы
3.1. Согласование среды фактического проекта со средой Storybook
Настройка Storybook как отдельной среды удобна, но если её параметры отличаются от параметров фактического приложения, это может создать дополнительные проблемы.
Например, в Storybook что-то может отображаться правильно, тогда как в фактическом приложении настройки alias или стилей применяются иначе.
Чтобы уменьшить это расхождение, я настроил проект так, чтобы уже используемые параметры Vite можно было применять и в Storybook.
framework: {
name: '@storybook/react-vite',
options: {},
},
viteFinal: async (config) => {
const { config: userConfig } = await loadConfigFromFile(
path.resolve(__dirname, '../vite.config.mts'),
);
return mergeConfig(config, {
...userConfig,
resolve: {
alias: {
'~': path.resolve(__dirname, '../src'),
},
},
});
},
Благодаря этой конфигурации такие параметры, как alias и способ обработки стилей, используемые в фактическом проекте, можно было максимально согласованно применять и в Storybook.
Кроме того, в настройках preview Storybook я настроил среду Provider, используемую фактическим приложением.
Например, в среде Storybook я также применил Provider для предоставления тем, Provider для управления запросами данных и Provider для обработки уведомлений.
Этот процесс был не просто настройкой для запуска Storybook; он был направлен на уменьшение различий между Storybook и фактическим приложением.
Хотя мы создали среду для независимой проверки UI, если бы она слишком сильно отличалась от фактического приложения, в итоге нам пришлось бы проводить проверку дважды.
3.2. Настройка Mock-данных для уменьшения зависимости от API
При применении Storybook наиболее важным для меня было уменьшение зависимости от API.
Многие реальные экраны строятся на данных, полученных с сервера. Поэтому простого отображения компонентов в Storybook было недостаточно для полноценного воспроизведения различных состояний.
Изначально можно было рассмотреть вариант непосредственной записи необходимых данных в каждый файл Story.
export const Default = {
args: {
data: {
// Story마다 필요한 Mock 데이터 작성
},
},
};
Однако с увеличением количества экранов и разнообразия состояний возрастала и вероятность повторения одинаковых или похожих Mock-данных в нескольких Story.
Поэтому я применил подход, при котором Mock-данные разделялись по назначению.
src
└── mocks
├── fixtures
└── handlers
В fixtures я организовал репрезентативные данные, используемые экранами, а в handlers настроил систему на перехват фактических запросов API и возврат нужных данных.
Это позволило относительно чётко разделить несколько состояний одного экрана.
Например, это можно было настроить следующим образом.
화면
├── 기본 상태
├── 빈 상태
├── 특정 조건 상태
└── 에러 상태
В Storybook я создал каждое состояние как отдельный Story, чтобы его можно было сразу проверить.
В результате я мог продолжать работу над UI, даже когда фактический backend ещё не был готов, а также уменьшить необходимость каждый раз создавать данные в реальной среде, когда требовалось проверить конкретное состояние.
4. Проблемы, возникшие во время фактической реализации
Применение Storybook не решило всех проблем между публикацией и разработкой.
Напротив, применение Storybook в реальном проекте сделало более заметными проблемы, которые ранее оставались практически незамеченными.
4.1 Ошибки в Story, вызванные переименованием компонентов
По мере развития проекта мы работали над упорядочиванием имен, чтобы четко различать роли компонентов.
После добавления к существующим именам компонентов суффиксов, обозначающих их роли, изменились имена нескольких файлов и пути их импорта.
Например, могли произойти следующие изменения.
JobDetail
↓
JobDetailWkr
В этом процессе также были затронуты пути импорта в файлах Story, которые уже были написаны.
// 변경 전
import { JobDetail } from './JobDetail';
// 변경 후
import { JobDetail } from './JobDetailWkr';
Изменение имени одного компонента само по себе может не представлять большой сложности. Однако если на этот компонент ссылаются файлы Story, масштаб изменений может оказаться шире, чем ожидалось.
Если бы репозитории публикации и разработки по-прежнему оставались раздельными, как раньше, я бы обнаружил это изменение только после возврата результатов работы. Однако, поскольку я работал с ветками в одном репозитории, изменения в ветке разработки немедленно проявились в виде конфликтов во время слияния, и нам пришлось сразу же их согласовать.
Благодаря этому опыту я понял, что Storybook — это не отдельный результат работы, изолированный от кода реального проекта, а код, на который также влияют изменения структуры проекта.
Я также почувствовал, что об изменениях, затрагивающих нескольких людей, например в структуре файлов или именовании, по возможности следует сообщать заранее.
Для тех, кто поддерживает файлы Story, даже небольшое предварительное уведомление может сократить ненужную работу по внесению изменений.
4.2 В Storybook нельзя было проверить всё
В процессе применения Storybook я ясно осознал, что это не инструмент, полностью заменяющий реальное приложение.
Хотя он очень эффективен для проверки состояний UI на уровне компонентов, сценарии, связывающие несколько экранов, и функции, зависящие от реального окружения, требовали отдельной проверки.
Например, к таким областям относились следующие.
- Навигация между экранами
- Переключение между несколькими приложениями
- Подключение реальных ответов API к UI
- Проблемы, возникающие только в реальном окружении выполнения
- Обработка сообщений от внешних окружений
Эти аспекты было трудно проверять в независимом окружении Storybook, либо для них требовались отдельные реализации Mock.
Сначала я считал, что лучше всего сделать в Storybook доступными как можно больше экранов. Однако после практического применения пришел к выводу, что перенос всего в Storybook сам по себе не должен становиться целью.
В конечном итоге более эффективным оказалось разграничить их роли.
Storybook
→ 컴포넌트 및 화면의 상태 확인
→ UI 리뷰
→ 다양한 데이터 상태 재현
→ 퍼블리싱 결과 공유
실제 개발 환경
→ 화면 간 이동 확인
→ 실제 API 연동 확인
→ 전체 사용자 흐름 확인
→ 실제 실행 환경 검증
Вместо того чтобы рассматривать Storybook и реальное приложение как конкурирующие инструменты, было уместнее использовать их как окружения для проверки с разными целями.
5. Сравнение до и после внедрения
|
Категория |
Прежний подход |
После внедрения Storybook |
|---|---|---|
|
Единица выполнения |
Требовался запуск всего окружения разработки |
Запускается только нужный компонент или экран |
|
Подготовка данных |
Зависела от реального API и состояния входа в систему |
Нужное состояние настраивается с помощью данных Mock |
|
Воспроизведение состояния |
Определенное состояние приходилось создавать вручную |
Состояние можно сразу проверить для каждой Story |
|
Проверка UI |
Требовалась навигация к нужному экрану |
Прямой доступ через соответствующую Story |
|
Метод повторной проверки |
Сценарий приходилось повторять каждый раз |
Состояние сразу воспроизводится с помощью сохраненной Story |
|
Подходящие области |
Проверка общего сценария и реальных интеграций |
Проверка состояний UI и компонентов |
Главное изменение после внедрения Storybook заключалось не просто в том, что просматривать экраны стало легче.
Раньше для проверки состояния определенного экрана сначала требовалось подготовить окружение и создать это состояние.
Однако с Storybook нужное состояние можно было создать как отдельную Story.
Иными словами, процесс подготовки к проверке экрана сократился, а после определения состояния его можно было стабильно воспроизводить в дальнейшем.
6. Извлечённые уроки из этого опыта
6.1 Главным преимуществом Storybook было воспроизведение состояний, а не самого UI
Сначала я воспринимал Storybook как инструмент для проверки компонентов в изоляции.
Однако, применив его в реальном проекте, я обнаружил, что его главным преимуществом была возможность многократно воспроизводить определённые состояния.
Помимо обычных состояний, я также мог задавать ситуации, которые было бы сложно создать в реальной среде, например пустые экраны или состояния ошибки.
Поскольку Story сохраняет одно и то же состояние после создания, её можно было многократно использовать при изменении и проверке UI.
6.2 Я мог продолжать работу, даже когда среда разработки не была готова
Случаи, когда ветка ещё не была объединена, а в более серьёзных ситуациях — когда я даже не мог войти в систему и открыть экран через среду разработки, происходили чаще, чем ожидалось.
Раньше мне пришлось бы запрашивать у команды разработки данные или информацию о состоянии учётной записи либо откладывать работу до восстановления нормальной работы среды.
Однако после того, как я начал использовать Storybook вместе с Mock-данными, я мог создавать и проверять нужные состояния экранов непосредственно в своей локальной среде даже в таких ситуациях. Я мог продолжать работать над UI, не запрашивая необходимые данные и не ожидая восстановления среды.
Из этого опыта я понял, что ценность Storybook заключается не столько в том, чтобы сделать экраны привлекательными, сколько в том, чтобы максимально снизить зависимость моей работы от готовности других частей проекта.
6.3 Целью не было создание каждого экрана в Storybook
По мере применения Storybook самым важным стало не то, насколько широко я использовал этот инструмент, а то, где он будет наиболее эффективен.
Storybook был особенно эффективен для экранов с большим количеством состояний UI, которые можно было достаточно полно проверить без реальных данных.
С другой стороны, для функций, в которых важны переходы между несколькими экранами или интеграция с реальной средой, было целесообразнее проводить проверку в существующей среде разработки.
Поэтому вместо того, чтобы управлять всеми экранами одинаково, я пришёл к выводу, что эффективнее сначала переносить в Storybook те экраны, проверка которых во время параллельной разработки требует наибольших затрат.
7. Заключение
Из этого опыта я понял, что Storybook — это не просто инструмент для отображения компонентов UI. Он также может служить средой для проверки, позволяющей самостоятельно проверять порученную мне работу над UI, даже когда среда разработки ещё не готова.
В частности, при использовании вместе с Mock-данными в ситуациях, когда ресурсы со стороны разработки, такие как API или вход в систему, ещё не готовы, этот подход оказался эффективным: я мог продолжать работу, многократно воспроизводя определённые состояния, не обращаясь к команде разработки и не ожидая.
Разумеется, Storybook не может самостоятельно решить все проблемы. Фактическую интеграцию с API, переходы между экранами и функции, зависящие от среды выполнения, по-прежнему необходимо проверять в реальной среде разработки.
Однако вместо попытки решить всё в одной среде эффективнее было разделить задачи: проверять состояния UI в Storybook, а реальные сценарии и интеграции — в настоящем приложении.
В конечном счёте главный урок, который я вынес из этого опыта, заключается в том, что важнее не сам Storybook как конкретный инструмент, а то, насколько независимо моя работа может выполняться от готовности других частей проекта.
В дальнейшем, работая над новыми проектами, я планирую не создавать каждый экран в Storybook с самого начала, а уделять приоритетное внимание областям, где проверка UI требует больших затрат из-за сильной зависимости от среды разработки или данных. Я считаю, что накопленные таким образом Stories могут служить не просто экранами для тестирования, а общим стандартом проверки UI и обсуждения его с командой.
природа