Найти тему
Nuances of programming

Как создать библиотеку компонентов React

Оглавление

Источник: Nuances of Programming

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

Почему? Потому что мы хотим создать масштабируемую систему, которая позволит постепенно производить обмен и совместно работать с более сложными компонентами. Тем самым можно будет ускорить разработку проекта намного эффективнее, чем при помощи конечной библиотеки.

Мы будем использовать Bit, инструмент с открытым исходным кодом, который предоставляет очень интересные возможности:

  • разработка изолированных компонентов, включая изолированные превью, тесты и сборки;
  • управление источниками компонентов: по сути, Git для отдельных компонентов;
  • управление зависимостями компонентов: автоматическое создание графиков зависимостей компонентов и интеллектуальное управление зависимостями.

Bit также содержит инструменты, упрощающие разработку компонентов:

  • предварительно настроенные среды разработки (например, CRA для компонентов);
  • инструменты, автоматически генерирующие package.json;
  • документацию по компонентам, использующую многомерные выражения, совместимые с Bit;
  • предварительный просмотр изолированных компонентов и многое другое.
-2
“Раскрывающийся” компонент React независимо контролируется исходным кодом, перемещается и публикуется. Ниже— его автоматически сгенерированный график зависимостей.
“Раскрывающийся” компонент React независимо контролируется исходным кодом, перемещается и публикуется. Ниже— его автоматически сгенерированный график зависимостей.

Создайте рабочее пространство Bit

Рабочее пространство Bit — это место, где компоненты будут разрабатываться и версионироваться независимо друг от друга.

Инициализируйте рабочее пространство Bit

  1. Установите Bit на свой компьютер.

Мы начнем с установки Bit version manager (BVM) и используем его для установки Bit.

$ npm i -g @teambit/bvm
$ bvm install

Для получения дополнительной информации и устранения неполадок см. документацию.

2. Инициализируйте новое рабочее пространство Bit с помощью шаблона react-workspace. Назовем рабочее пространство my-component-library:

$ bit new react-workspace my-component-library

новое рабочее пространство успешно создано на path/to/my-component-library

3. Установите все зависимости рабочего пространства:

$ bit install

Настройка удаленной области для размещения компонентов

Компоненты с индивидуальным управлением исходным кодом перемещаются не на стандартный хостинг Git (например, GitHub), а в удаленные области. Каждая область может содержать несколько компонентов (в качестве независимых мини-репозиториев). Это позволяет нам устанавливать разные разрешения для разных компонентов, даже если они созданы в одном и том рабочем пространстве Bit.

Bit.dev — это реестр пакетов и облачный хостинг для компонентов. Мы будем использовать его для публикации и установки пакетов, а также для совместной работы над компонентами. Вы можете изменить настройки рабочего пространства, чтобы использовать свой собственный хостинг компонентов и реестр пакетов узлов (например, реестр npm). Смотрите документацию Bit, чтобы получить более подробную информацию.

  1. Перейдите на bit.dev, чтобы зарегистрировать бесплатный аккаунт и создать свою собственную удаленную область (или коллекцию).
  2. Откройте файл workspace.jsoncи настройте свойство defaultScope для вашего имени пользователя и названия области.

// file: workspace.jsonc

{
"$schema": "https://static.bit.dev/teambit/schemas/schema.json",
"teambit.workspace/workspace": {
"name": "my-component-library",
"defaultDirectory": "{scope}/{name}",

// <scope-owner>.<scope-name>
"defaultScope": "our-org.my-scope"
// ...
}

Запустите сервер Bit Dev и пользовательский интерфейс рабочего пространства

Пользовательский интерфейс рабочего пространства позволяет нам исследовать компоненты, управляемые этим пространством, и получать обратную связь в режиме реального времени о состоянии каждого компонента (обнаруженные проблемы и т. д.). С его помощью можно также запускать различные службы разработки в “режиме наблюдения” (например, тестирование, компиляция и т. д.).

$ bit start

НАЗВАНИЕ СРЕДЫ URL СТАТУС
teambit.react/react http://localhost:3100 RUNNING

Теперь вы можете просмотреть компоненты 'my-component-library' в браузере.
Сервер Bit работает на
http://localhost:3000

Пример пользовательского интерфейса рабочего пространства, отображающего компоненты пространства в режиме реального времени
Пример пользовательского интерфейса рабочего пространства, отображающего компоненты пространства в режиме реального времени

Создайте файлы компонента

Мы будем использовать готовый шаблон Bit для компонентов React. Назовем компонент button (кнопка) и поместим его в пространство имен inputs (вводы). Пространства имен помогают нам организовать компоненты в рабочем пространстве, а затем в удаленной области.

$ bit create react-component inputs/button

the following 1 component(s) were created

my-scope/inputs/button
location: my-scope/inputs/button
env: teambit.react/react

Использовать шаблон компонента необязательно. Подробнее об этом читайте в документации.

Отслеживание нового компонента

Файлы компонентов были сгенерированы и теперь отслеживаются как один компонент. Проверьте файл рабочего пространства .bitmap (в корневом каталоге рабочего пространства), чтобы убедиться, что компонент button был добавлен.

-5

Свойство version пусто, так как компонент еще не помечен версией выпуска.

Перейдите к пользовательскому интерфейсу рабочего пространства (работает на http://localhost:3ooo) для отображения вашего компонента.

Поскольку Bit Harmony находится в бета-версии, вы можете столкнуться с ошибками. Если это произойдет, перезапустите сервер разработки Bit (Ctrl+C и bit start).

-6

Давайте теперь рассмотрим сгенерированные файлы компонента, чтобы сделать из него настоящую кнопку.

Файл реализации: button.tsx

Сейчас компонент возвращает элемент div, а не кнопку. Давайте изменим это в файле button.tsx. Мы также добавим к нему состояние loading.

import React, { ButtonHTMLAttributes } from 'react';

export type ButtonProps = {
/* Determines whether a button is in 'loading' state */
isLoading?: boolean;
} & ButtonHTMLAttributes<HTMLButtonElement>;

export function Button({
children,
isLoading,
disabled,
...rest
}: ButtonProps) {
return (
<button disabled={isLoading || disabled} {...rest}>
{isLoading ? 'Loading...' : children}
</button>
);
}

Button.defaultProps = {
disabled: false,
isLoading: false,
};

Предварительный просмотр изолированных компонентов: button.composition.tsx

-7

Композиции — это своего рода мини-приложения, которые тестируют компонент в возможных контекстах. Они используются для предварительного просмотра компонента. С их помощью мы как авторы и специалисты по сопровождению получаем подтверждение того, что компонент успешно интегрируется в будущие приложения (до момента его совместного использования).

Композиции не отражают последние обновления. Изменим это, заменив текущую композицию двумя новыми — одной для кнопки в состоянии по умолчанию, а другой — в момент загрузки:

import React from 'react';
import { Button } from './button';

export const ButtonInDefaultState = () => <Button>Click Me!</Button>;

export const ButtonInLoadingState = () => <Button isLoading>Click Me!</Button>;

-8

Документация по компонентам: button.docs.mdx

Это файл документации многомерных выражений, совместимый с Bit, который позволяет нам интегрировать JSX с Markdown и добавлять специальные Bit-свойства (метаданные). Файл doc загружается с помощью Bit и отображается на странице обзора компонента.

Файл doc уже импортирует сюда компонент button, чтобы сделать его доступным для рабочих версий документа. Все, что нам осталось, — это изменить документацию, чтобы лучше описать измененный компонент:

---
description: 'A basic button component.'
labels: ['react', 'input']
---

import { Button } from './button';

Это базовая кнопка с состоянием *'loading'*.

### Использование кнопки

```js
<Button>Submit</Button>
```

### Рабочая версия: Установка кнопки в состояние 'loading'

Добавьте или удалите `isLoading` для изменения ее состояния.

```js live
<Button isLoading>Submit</Button>
```

-9

Тестирование компонентов: button.spec.tsx

Текущее тестирование пытается использовать ранее удаленные композиции.

-10

Давайте обновим тестовый файл с помощью соответствующих тестов, используя новые композиции:

import React from 'react';
import { render } from '@testing-library/react';
import { ButtonInDefaultState, ButtonInLoadingState } from './button.composition';

describe('Button', () => {
it('should render with its default text', () => {
const { getByText } = render(<ButtonInDefaultState />);
const rendered = getByText('Click Me!');
expect(rendered).toBeTruthy();
});

it('should render in a loading state', () => {
const { getByText } = render(<ButtonInLoadingState />);
const rendered = getByText('Loading...');
expect(rendered).toBeDisabled();
});
});

Еще раз проверим состояние теста в пользовательском интерфейсе рабочего пространства:

-11

Создайте компонент и пометьте его версией выпуска

Теперь, когда компонент button готов, давайте пометим его первой версией выпуска:

$ bit tag inputs/button 1.0.0 --message "first release version"

...
новые компоненты
(первая версия для компонентов)
> inputs/button@1.0.0

Команда bit tag выполнит процесс сборки компонента, прежде чем пометит его новой версией выпуска. Процесс сборки определяется средой разработки (в нашем случае средой разработки React) и несколькими предварительно настроенными задачами сборки Bit. Сам процесс сборки полностью настраиваемый.

В процесс сборки компонентов входят следующие этапы:

  • тестирование компонента в изолированном каталоге, удаленном из его рабочего пространства;
  • компиляция исходного кода (в React env используется компилятор TypeScript);
  • автоматическое создание распространяемого пакета Node при помощи Bit (вместе с автоматически генерируемым файлом package.json);
  • объединение предварительных просмотров (композиций) компонента и документации (в React env используется webpack);
  • создание журнала сборки;
  • и т. д.

Наш версионированный компонент будет содержать в себе все встроенные артефакты, а также настройки среды разработки и график зависимостей.

Версия выпуска хранится в виде Git-подобных объектов в каталоге .bit / .git/bit (также известном под названием локальная область).

Экспорт: отправка и публикация компонентов

Теперь, когда готова неизменяемая версия выпуска компонента, мы можем экспортировать ее, чтобы поделиться с другими пользователями и сотрудниками.

$ bit export

exported the following 1 component(s):
our-org.my-scope/inputs/button

При экспорте версия выпуска компонента (объекты, подобные Git) отправляется на настроенный удаленный хостинг, а пакет компонента публикуется в реестре bit.dev (но, опять же, это можно изменить).

Пример: удаленная область, в которой размещены “экспортированные” компоненты
Пример: удаленная область, в которой размещены “экспортированные” компоненты

Импорт: клонирование компонента в рабочее пространство

Пакеты компонентов могут быть установлены в рабочих пространствах Bit с помощью Bit (например, bit install <package-name>). Их также можно установить в не-Bit проектах с использованием стандартных клиентов NPM (таких как npm или Yarn). Подробнее об этом читайте в документации.

Но самое интересное в компонентах, совместно используемых с Bit, заключается в том, что над ними можно работать, “импортируя” (клонируя) их в рабочие пространства Bit.

Давайте импортируем компонент dots-loader из области удаленного обучения, принадлежащей teambit. Для этого перейдем на страницу компонента dots-loader, скопируем команду импорта и запустим ее.

страница компонента dots-loader
страница компонента dots-loader

$ bit import teambit.teaching/ui/elements/dots-loader

...
successfully imported one component
- added teambit.teaching/ui/elements/dots-loader new versions: 0.0.1, 0.0.2, 0.0.3, currently used version 0.0.3

Импортированный компонент теперь доступен в локальном рабочем пространстве. Его исходные файлы находятся в каталоге teaching , а пакет — в каталоге node_modules под именем владельца (teambit).

-14

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

Чтобы просмотреть настройки импортированных компонентов, выполните следующую команду:

$ bit show ui/elements/dots-loader

Настройки импортированного компонента dots-loader
Настройки импортированного компонента dots-loader

Обработка зависимостей компонентов

“Выпадающий компонент”, разработанный изолированно с помощью Bit. Зависимости компонента также генерируются и управляются посредством Bit.
“Выпадающий компонент”, разработанный изолированно с помощью Bit. Зависимости компонента также генерируются и управляются посредством Bit.

Теперь, когда у нас есть компонент dots-loader, давайте используем его для замены текста “Загрузка…” (“Loading…”) в компоненте button (отображается в состоянии загрузки). Мы сделаем это с помощью импорта компонента, используя его имя пакета.

import React, { ButtonHTMLAttributes } from 'react';
import { DotsLoader } from '@teambit/teaching.ui.elements.dots-loader';

export type ButtonProps = {
/* Determines whether a button is in 'loading' state */
isLoading?: boolean;
} & ButtonHTMLAttributes<HTMLButtonElement>;

export function Button({
children,
isLoading,
disabled,
...rest
}: ButtonProps) {
return (
<button disabled={isLoading || disabled} {...rest}>
{isLoading ? <DotsLoader/> : children}
</button>
);
}

Button.defaultProps = {
disabled: false,
isLoading: false,
};

Перейдите в пользовательский интерфейс рабочего пространства, чтобы просмотреть новые композиции компонентов:

-17

Теперь у нас есть компонент, зависящий от другого компонента.

-18

Как только компонент dots-loader будет изменен и помечен новой версией выпуска, Bit автоматически протестирует, соберет и пометит зависимый компонент button.

Обновления компонента dots-loader теперь будут инициировать процессы сборки и пометок в его зависимом компоненте button.

Если бы существовали какие-либо другие прямые или косвенные зависимые компоненты, процессы сборки и пометок также касались бы и их тоже.

При использовании Bit вместе с Bit.dev этот волновой эффект выходит за пределы локального рабочего пространства и распространяется на все экспортируемые компоненты во всех удаленных областях.

Пример: Ripple CI проходит через все компоненты, зависящие от обновленных вкладок
Пример: Ripple CI проходит через все компоненты, зависящие от обновленных вкладок

Заключение

Надеюсь, из этой статьи вы узнали общую суть работы с Bit. Это перспективный инструмент, который может радикально изменить способ сотрудничества при работе над веб-проектами.

Читайте также:

Читайте нас в Telegram, VK

Перевод статьи Alicia Jones: How To Create a React Component Library