Введение
В наши дни разработка интерфейса является достаточно затратным процессом который требует усилий от множества людей, разработчиков, дизайнеров, тестировщиков продукт менеджеров и так далее.
Компании все чаще прибегают к написанию интерфейса состоящего из множества независимых компонентов, которые могут быть использованы повторно. Многие дизайнеры создают дизайн проект который описывает каждую деталь дизайна. Они используют ряд инструментов для документирования интерфейсов, первые которые приходтя на ум это axshare.com и zeplin.com. Тот же фотошоп, в котором у них все разложено строго по папочкам. Это позволяет им с легкостью работать над дизайном проекта, обновлять и добавлять новые страницы, просто копируя уже имеющиеся наработки.
А что же касается разработчиков? Да у нас есть Angular, React, Vue, Ember, Polymer. Все эти инструменты в той или иной мере позволяют нам создавать компоненты с дальнейшим их повторным использованием. Но скажите мне каким образом, вы можете взглянуть на проект так же как это делает дизайнер? Где я могу увидеть все компоненты которые используются в проекте, узнать их свойства или же просто попробовать? Как я могу узнать реализован ли нужный мне компонент? Такие вопросы уже начинают возникать в проектах среднего масштаба. Разумеется я могу пойти и спросить коллегу, но это излишнии коммуникации, которые неэффективны ввиду множества причин. Коллега попросту может не вникнуть в суть вашей проблемы и указать вам на схожий компонент который вы будете еще долго доделывать.
Типичная ситуация когда вы находитесь на стадии оценки новой функциональности, пройдясь по документации новой страницы которую вам предстоит разработать, все компоненты выглядят знакомыми, все они уже где-то используются и вы оцениваете новую задачу делая ставку на то, что некоторые компоненты уже реализованы. Договорившись о сроках и начав новый спринт, немного покопавшись в коде, вы в ужасе осознаете, что переиспользовать компонент не получится, что он зависит сугубо от других компонентов и вообще это все концептуально неверно.
У вас есть только два выхода
- Копипаст и создания еще одного похожего компонента.
- Разработка нового компонента, многофункционального компонента.
Разумеется есть и 3тий вариант, улучшить/расширить старый компонент. Но как подсказывает мне опыт, это еще затратней чем написать новый. Трудозатраты на исправление ошибок растут с каждым новым этапом развития проекта. Чем фундаментальней недороботка тем дороже ее исправлять.
Добросовестным выбором будет разработка нового компонента. Но тут вам передается эстафета того недобросовестного разработчика. Учитывая, что сроки горят, вы может быть и успеете разработать новый компонент, но сделать его общим у вас уже не будет времени.
На вопрос почему так произошло можно ответить следующим образом:
- Разработчик который разрабатывал компонент эгоист и не думал о будущей судьбе компонента.
- Раньше не планировалось переиспользование этого компонента где либо еще.
- Вы не знали, что этот компонент переиспользовать нельзя.
- Вы не знали о существовании более подходящего компонента.
С растущей тенденцией на распределенную разработку и компоненты которые можно повторно использовать, появляется необходимость в дополнительном инструментарии. Существует огромное количество различных инструментов под различные задачи и нужны фронт-енд разработчиков.
В этой статье я хотел бы осветить React Storybook для компонентов написанных с использованием React.js и Vue.js или даже React Native. С его использованием в проекте, можно с легкостью избежать описанных выше ситуаций.
Storybook это окружения для разработки UI компонентов. Storybook позволяет просматривать библиотеку компонентов, увидеть различные состояния компонентов и интерактивно разрабатывать и тестировать компоненты.
Storybook запускается отдельно от вашего приложения. Это позволяет разрабатывать компоненты в изоляции, что улучшает возможность переиспользование компонентов, тестируемость и скорость их разработки. Вы можете создавать новый компоненты быстро и без каких либо зависимостей основного проекта
Тут вы можете посмотреть примеры использования Storybook https://storybook.js.org/examples/
Storybook имеет множество расширений и богатый API для расширения его функциональных возможностей, а также поддержку React Native.
Давайте рассмотрим использование Storybook с позиции различных участников процесса создания и второстепенных процессов поддержки интерфейса приложения.
Как UIUX дизайнер
У вас будет возможность попробовать в живую и проверить реализованный разработчиком компонент. Увидеть все возможные состояние компонента и предоставить полноценный фидбек.
Как разработчик
У вас будет библиотека компонентов, вы больше не будете биться в догадках, есть ли у вас такой-то компонент или нет, вы сможете попробовать, поиграться с компонентом и узнать возможности его использования в рамках вашей текущей задачи. Это очень важно как для разработчика, иметь возможность увидеть все компоненты которые используются в проекте и знать все их особенности. Вы конечно же можете потратить уйму времени на изучение исходного кода, но будет куда проще найти нужный компонент с нужными свойствами визуально, а потом уже вдаваться в подробности.
Вы сможете разрабатывать компоненты в изолированном окружении, которое не требует поднятие всего проекта локально. Изолированное окружение не явным образом стимулирует вас разрабатывать компоненты с более продуманным API и с мыслью о возможности его переиспользования в любой части проекта. Вы думаете о входящих параметрах, с точки зрения пользователя и понимаете какие параметры были бы удобны потенциальному пользователю. Также вы задумываетесь об изоляции стилей. Помимо всего прочего, вы получаете настоящий верстак для разработки компонентов. Вы можете настроить окружение Storybook как вам угодно и использование таких вещей как HMR вы получаете из коробки.
Как тестировщик
У вас будет возможность тестировать каждый компонент в отдельности и независимо от других. Нет необходимости в запуске целого проекта. Вы можете просто открыть Storybook с интересующим вас компонентов и проводить абсолютно любые E2E тесты.
Как продакт менеджер
Продакт менеджер зачастую работает совместно с дизайнером, ведь это именно он говорит, какой бы функционал он хотел бы видеть. Как продукт менеджеру, работая над новой страницей вам будет полезно знать уже существующие элементы и иметь возможность попробовать их интерактивно. И словно дизайнер набросать новый скетч из уже существующих кусочков.
Установка
Та как Storybook находит в экосистеме node/npm, это делается очень просто. Установить основной cli инструмент можно с помощью одного из ваших любимы пакетных менеджеров Yarn или NPM.
yarn global add @storybook/cli
Теперь вы можете использовать этот инструмент для инициализации Stroybook’а в вашем проекте.
Для экспериментов нам понадобится проект. В качестве примера возьмем заготовку из create-react-app. Я опущу описание и особености create-react-app, это очень полезный и простой для понимания инструмент, детальней вы можете прочитать тут.
Установим и создадим новый проект с помощью create-react-app
yarn global add create-react-appi
Создадим проект
create-react-app my-app
Перейдем в директорию проекта
cd my-app
И запустим его
yarn start
В браузере откроется свеженький проект созданный с использованием create-react-app.
Теперь у нас есть приложение для экспериментов со Storybook, что ж давайте приступим.
Для того, чтобы инициализировать Storybook выполните следующую команду находясь в корне проекта
getstorybook
Эта команда определяет тип проекта, делает необходимые проверки и устанавливает зависимости
После чего в проекте появится новосозданные папки .storybook и stories
Папка .storybook содержит всевозможные конфигурационные файлы. С ними мы разберемся позже. На данный момент нас интересует папка stories.
В ней хранится библиотека компонентов. После инициализации Storybook в проекте, по умолчанию создается файл с одним примером. Давайте запустим Storybook и посмотрим на него.
yarn storybook
Storybook будет доступен по адресу http://localhost:6006/
Страница имеет простой интерфейс
Слева мы видим панель с иерархическими папками компонентов с возможностью поиска.
Справа достаточно большая рабочая область, в которой будут отображаться ваши компоненты и прочая информация.
И панель снизу которая используется как интерактивный инструмент, на которую вы можете выводить различную информацию и элементы управления компонентов.
Расположение этих панелей конфигурируется
И так, давайте возьмем какой нибудь компонент за основу, чтобы не тратить время и не писать свой.
Я выбрал react-select
yarn add react-select
Создайте папку Select с файлом index.js в src следующего содержания
import React, { Component } from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
class SelectWrapper extends Component {
state = {
value: null
}
onChange = (value) => {
this.setState({
value,
})
this.props.onChange(value)
}
render() {
return (
<Select { ...this.props } value={this.state.value} onChange={this.onChange} />
)
}
}
SelectWrapper.defaultProps = {
onChange: () => {}
}
export default SelectWrapper;
Это просто небольшая обертка для хранения состояния.
Теперь давайте добавим наш компонент в Storybook
Делается это очень просто:
import Select from '../Select'
storiesOf("React select", module)
.add('General', () => <Select options={options} />)
Код интуитивно понятен. storiesOf создает категорию, в которую вы можете добавлять различные компоненты.
Давайте добавим react-select в наш Storybook с возможностью мультивыбора
storiesOf("React select", module)
.add('General', () => <Select options={options} />)
.add('With multi prop', () => <Select options={options} multi />) // Мультивыбор
Сборка Storybook
Не маловажной особенностью является возможность собрать Storybook в статичные файлы, которые можно будет например опубликовать на каком либо сайте или использовать внутри компании в качестве документации.
Просто запустите
yarn build-storybook
По умолчанию файлы складываются в storybook-static. Вы можете открыть их в любом браузере.
Webpack и прочая конфигурация
По умолчанию Storybook пытается разобраться в вашем окружении и использовать ряд настроек которые позволяют собрать и отобразить Storybook. Но бывают случаи когда без дополнительной конфигурации не обойтись.
Вы можете добавить webpack.config.js в директорию .storybook.
Зачастую такой конфиг будет очень простым
// you can use this file to add your custom webpack plugins, loaders and anything you like.
// This is just the basic way to add additional webpack configurations.
// For more information refer the docs: https://storybook.js.org/configurations/custom-webpack-config
// IMPORTANT
// When you add this file, we won't add the default configurations which is similar
// to "React Create App". This only has babel loader to load JavaScript.
const mainConfig = require('../webpack.config')
module.exports = {
plugins: [
// your custom plugins
],
module: mainConfig.module
};
Как вы видите, это просто импорт конфига из основного проекта. В наших экспериментах вам данный конфиг не понадобится.
Использование дополнений
Storybook имеет ряд рекомендуемых дополнений
- storyshots — Снапшот тестинг
- actions — Логирование действий
- links — Создание ссылок между страницами Storybook
- comments — Комментирование
- info — Аннотация компонентов
- knobs — Редактирование пропертей компонентов
- options — Кастомизирование UI Storybook’а
Давайте вернемся и посмотрим на созданные по умолчанию примеры
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
storiesOf('Button', module)
.add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
.add('with some emoji', () => <Button onClick={action('clicked')}> </Button>)
дополнение action, создает своего рода функцию, результат выполнения которой вы увидете в Action Logger. Это может быть удобно для логирования параметров по типу onApply или onClick.
Достаточно полезными являются так называемые knobs. Они позволяют редактировать передаваемые параметры в компонент.
yarn add @storybook/addon-knobs
Необходимо импортировать установленный модуль в addons.js в директории .storybook
import '@storybook/addon-knobs/register'
И в stories/index.js импортировать необходимые нам knobs
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
Давайте добавим возможность интерактивного манипулирования кнопкой
storiesOf('Button', module)
.addDecorator(withKnobs)
.add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
.add('with some emoji', () => <Button onClick={action('clicked')}> </Button>)
.add('Interactive demo', () => <Button disabled={boolean('Disabled', false)}>{text('Button text', 'Default')}</Button>)
Теперь мы можем изменять текст кнопки и с помощью boolean задавать состояние кнопки.
Еще одним очень полезным дополнением является Info, данное дополнение автоматически документирует внешний API компонента.
yarn add @storybook/addon-info
Импортируете модуль
import { withInfo } from '@storybook/addon-info';
И давайте немного изменим код нашей кнопки
.add('Interactive demo 2', withInfo('doc string about my button component')(() =>
<Button disabled={boolean('Disabled', false)}>{text('Button text', 'Default')}</Button>
)
Справа появится кнопка, с помощью которой вы можете открыть подробную информацию о компоненте
Также можно отобразить эту информацию без необходимости ее открытия, прямо на рабочей области вместе с компонентом.
.add('Interactive demo 3', withInfo({
text: 'doc string about my button component',
inline: true,
})(() =>
<Button disabled={boolean('Disabled', false)}>{text('Button text', 'Default')}</Button>
))
Заключение
React Storybook как вы видите, очень прост в использовании, имеет множество всевозможных настроек, дополнений и позволяет вам решить проблемы с поддержкой библиотеки компонентов. Остальные члены команды могут увидеть и попробовать компонент еще до того как он будет прикручен к странице, что позволяет получить фидбек от дизайнеров намного раньше. Новички в команде больше не будут теряться в догадках, есть ли у вас тот или иной компонент и можно ли его использовать в рамках текущей задачи.
Автор: Ольховой Дмитрий