Большую часть свой работы, я пишу бэкенды, но вот на днях появилась задача начать библиотеку компонентов на React. Несколько лет назад, когда версия React была такой же маленькой, как и мой опыт фронтенд-разработки, я уже делал подход к снаряду и получилось неумело и коряво. Принимая во внимание зрелость текущей экосистемы React и мой подросший опыт, я воодушевился уж в этот-то раз сделать всё хорошо и удобно. В результате у меня появилась заготовка для будущей библиотеки, а чтобы ничего не забыть и собрать всё в одном месте, была написана эта статья-шпаргалка, которая также должна помочь тем, кто не знает, с чего начать. Посмотрим, что же у меня получилось.
TL/DR: Код готовой к старту библиотеки можно посмотреть на github
К задаче можно подойти с двух сторон:
- Найти готовый starter-kit, Boilerplate или cli-генератор
- Собрать всё самому
Первый способ хорош для быстрого старта, когда вы совершенно не хотите разбираться с конфигурированием и подключением необходимых пакетов. Также этот вариант подойдёт для новичков, кто не знает с чего начать и в чём должно быть отличие бибилиотеки от обычного приложения.
Вначале я пошёл первым путём, но затем решил обновить зависимости и прикрутить ещё пару пакетов, и тут посыпались всякие ошибки и несостыковки. В итоге закатал рукава и сделал всё сам. Но генератор библиотек таки упомяну.
Create React Library
Большинство разработчиков, которые имели дело с React слышали про удобный стартер приложений на React, который позволяет свести конфигурацию проекта к минимуму и предоставляет разумные дефолты — Create React App (CRA). В принципе, его можно было бы использовать и для библиотеки (и есть статья на хабре). Однако, структура проекта и подход к разработке ui-kit немного отличается от обычного SPA. Нам нужен отдельный каталог с исходниками компонентов (src), песочница для их разработки и отладки (example), инструмент документирования и демонстрации ("витрина") и отдельный каталог с подготовленными к экспорту файлами (dist). Также компоненты библиотеки не будут складываться в SPA приложение, а будут экспортироваться через индексный файл. Подумав об этом, я отправился на поиски и быстро обнаружил подобный CRA пакет — Creat React Library (CRL).
CRL, также как и CRA, является "easy-to-use" CLI-утилитой. С помощью неё можно сгенерировать проект. Он будет содержать:
- настроенный Rollup для сборки cjs и es модулей и source map с поддержкой css-модулей
- babel для транспиляции в ES5
- Jest для тестов
- TypeScript (TS) как опция, которой мы хотели бы воспользоваться
Для генерации проекта библиотеки выполним(npx позволяет не устанавливать пакеты глобально):
npx create-react-library
И в результате работы утилиты получим сгенерированный и готовый к работе проект библиотеки компонентов.
На сегодняшний день зависимости немного устаревшие, поэтому я решил обновить их всех до последних версий с помощью npm-check:
npx npm-check -u
Ещё одним печальным фактом является то, что приложение-песочница в каталоге example
генерируется на js. Придётся руками переписать его на TypeScript, добавив tsconfig.json
и некоторые зависимости (например, сам typescript
и основные @types
).
Также пакет react-scripts-ts
объявлен deprecated
и больше не поддерживается. Вместо него следует установить react-scripts
, потому что с некоторых пор CRA (чьим пакетом является react-scripts
) поддерживает TypeScript из коробоки (с помощью Babel 7).
В итоге я не осилил натягивание конфига react-scripts
на мое представление о библиотеке. Насколько я помню, Jest из этого пакета требовал опции компилятора isolatedModules
, которая шла в разрез с моим желанием генерировать и экспортировать d.ts
из библиотеки (всё это как-то связано с ограничениями Babel 7, который используется Jest и react-scripts
для компиляции TS). Поэтому я сделал eject
для react-scripts
, посмотрел на результат и переделал всё руками, о чём и пишу далее.
tsdx
Спасибо пользователю StanEgo, который рассказал про отличную альтернативу Create React Library — tsdx. Эта cli-утилита также похожа на CRA и в одну команду создат основу для вашей библиотеки с настроенным Rollup, TS, Prettier, husky, Jest и React. Причем React идёт как опция. Достаточно просто выполнить:
npx tsdx create mytslib
И в результате будут установлены необходимые свежие версии пактов и сделаны все настройки. Получим похожий на CRL проект. Основное отличие от CRL — Zero-config. Т. е. конфиг Rollup скрыт от нас в tsdx (также как это делает CRA).
Быстро пробежавшись по документации, я не нашёл рекомендуемых способов более тонкой конфигурации или что-то вроде eject как в CRA. Заглянув в issue проекта, обнаружил, что пока такой возможности нет. Для каких-нибудь проектов это может быть критично, в этом случае придётся немного поработать руками. Если же вам это не нужно, то tsdx отличный способ, чтобы быстро начать.
Берём управление в свои руки
А что, если пойти вторым путём и собрать всё самому? Итак, начнём с начала. Запускаем npm init
и генерируем package.json
для библиотеки. Добавим туда немного информации о нашем пакете. Например, пропишем минимальные версии для node и npm в поле engines
. Собранные и эспортируемые файлы будем помещать в каталог dist
. Укажем это в поле files
. Мы создаём библиотеку компонентов react, поэтому рассчитываем на то, что у пользователей будут стоять необходимые пакеты — прописываем в поле peerDependencies
минимальные необходимые версии react
и react-dom
.
Теперь установим пакеты react
и react-dom
и необходимые types (т.к. мы будем пилить компоненты на TypeScript) как devDependencies (как и все пакеты в этой статье):
npm install --save-dev react react-dom @types/react @types/react-dom
Установим TypeScript:
npm install --save-dev typescript
Создадим файлы конфигурации для основного кода и тестов: tsconfig.json
и tsconfig.test.json
. Наш target
будет в es5
, будем генерировать sourceMap
и т.д. С полным списком возможных опций и их значений можно ознакомиться в документации. Не забудем в include
указать каталог с исходниками, а в exclude
добавить каталоги node_modules
и dist
. В package.json
укажем в поле typings
, где брать типы для нашей библиотеки — dist/index
.
Создадим каталог src
для исходников компонентов библиотеки. Добавим всякие мелочи, вроде .gitignore
, .editorconfig
, файла с лицензией и README.md
.
Rollup
Для сборки будем использовать Rollup, как предлагал CRL. Необходимые пакеты и конфиг, я подсматривал также у CRL. Вообще слышал мнение, что Rollup хорош для библиотек, а Webpack для приложений. Однако, я не конфигурировал Webpack (мне хватало того, что делает за меня CRA), но Rollup действительно хорош, прост и красив.
Установим:
npm install --save-dev rollup rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-peer-deps-external rollup-plugin-postcss rollup-plugin-typescript2 rollup-plugin-url @svgr/rollup
В package.json
добавим поля с распложением собранных бандлов библиотеки, как рекомендует нам rollup
— pkg.module:
"main": "dist/index.js",
"module": "dist/index.es.js",
"jsnext:main": "dist/index.es.js"
import typescript from 'rollup-plugin-typescript2';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import resolve from 'rollup-plugin-node-resolve';
import url from 'rollup-plugin-url';
import svgr from '@svgr/rollup';
import pkg from './package.json';
export default {
input: 'src/index.tsx',
output: [
{
file: pkg.main,
format: 'cjs',
exports: 'named',
sourcemap: true
},
{
file: pkg.module,
format: 'es',
exports: 'named',
sourcemap: true
}
],
plugins: [
external(),
postcss({
modules: false,
extract: true,
minimize: true,
sourceMap: true
}),
url(),
svgr(),
resolve(),
typescript({
rollupCommonJSResolveHack: true,
clean: true
}),
commonjs()
]
};
Конфиг представляет собой js-файл, а точнее экспортируемый объект. В поле input
указываем файл, в котором прописаны экспорты для нашей библиотеки. output
— описывает наши ожидания на выходе — в модуль какого формата скомпилировать и куда его положить.
- rollup-plugin-peer-deps-external — позволяет исключить
peerDependencies
изbundle
, чтобы уменьшить его размер. Это резонно, ибо наличиеpeerDependencies
ожидается от пользователя библиотеки - rollup-plugin-postcss — интегрирует PostCss и Rollup. Тут мы отключаем css-modules, включаем в экспортную поставку от нашей библиотеки css, минимизируем его и включаем создание sourceMap. Если вы не экспортируете никакого css, кроме используемого компонентами библиотеки, то
extract
можно избежать — необходимый в компонентах css будет по необходимости добавлен в тег head на странице в конечном итоге. Однако в моём случае необходимо раздавать ещё некоторый дополнительный css (сетка, цвета и т.п.), и клиенту придётся явно подключать себе css-bundle библиотеки. - rollup-plugin-url — позволяет экспортировать различные ресурсы, вроде картинок
- svgr — трансформирует svg в React-компоненты
- rollup-plugin-node-resolve — определяет расположение сторонних модулей в node_modules
- rollup-plugin-typescript2 — подключает компилятор TypeScript и предоставляет возможность для его конфигурации
- rollup-plugin-commonjs — конвертирует commonjs-модули зависимостей в es-модули, чтобы их можно было включить в bundle
Добавим в поле scripts
package.json
команду для сборки ("build": "rollup -c"
) и запуска сборки в watch-режиме во время разработки ("start": "rollup -c -w && npm run prettier-watch"
).
Первый компонент и экспортный файл
Теперь напишем простейший react-компонент, чтобы проверить как работает наша сборка. Каждый компонент в библиотеке будем помещать в отдельный каталог в родительском каталоге — src/components/ExampleComponent
. В этом каталоге будут содержаться все связанные с компонентом файлы — tsx
, css
, test.tsx
и проч.
Создадим какой-нибудь файл стилей для компонента и tsx
-файл самого компонента.
/**
* @class ExampleComponent
*/
import * as React from 'react';
import './ExampleComponent.css';
export interface Props {
/**
* Simple text prop
**/
text: string;
}
/** My First component */
export class ExampleComponent extends React.Component<Props> {
render() {
const { text } = this.props;
return (
<div className="test">
Example Component: {text}
<p>Coool!</p>
</div>
);
}
}
export default ExampleComponent;
Также в src
надо создать файл с общими для библиотеками типами, где будет объявлен тип для css и svg (подсмотрено у CRL).
/**
* Default CSS definition for typescript,
* will be overridden with file-specific definitions by rollup
*/
declare module '*.css' {
const content: { [className: string]: string };
export default content;
}
interface SvgrComponent extends React.FunctionComponent<React.SVGAttributes<SVGElement>> {}
declare module '*.svg' {
const svgUrl: string;
const svgComponent: SvgrComponent;
export default svgUrl;
export { svgComponent as ReactComponent };
}
Все экспоритруемые компоненты и css должны быть указаны в экспортном файле. У нас это — src/index.tsx
. Если какой-то css не используется в проекте и не указан в составе импорируемых в src/index.tsx
, то он будет выкинут из сборки, что прекрасно.
import { ExampleComponent, Props } from './ExampleComponent';
import './export.css';
export { ExampleComponent, Props };
Теперь можно попробовать собрать библиотеку — npm run build
. В результате запуститься rollup
и соберёт нашу библиотеку в бандлы, которые мы найдём в каталоге dist
.
Далее добавим несколько инструментов для повышения качества нашего процесса разработки и его результата.
Забываем о форматировании кода с Prettier
Терпеть не могу в code-review указывать на небрежное или нестандартное для проекта форматирование, а тем более спорить про него. Подобные недочёты естественно должны быть исправлены, однако разработчикам лучше сосредоточиться на том, что и как код делает, а не как он выглядит. Эти исправления — первый кандидат на автоматизацию. Есть прекрасный пакет под эту задачу — prettier. Установим его:
npm install --save-dev prettier
Добавим конфиг для небольшого уточнения правил форматирования.
{
"tabWidth": 3,
"singleQuote": true,
"jsxBracketSameLine": true,
"arrowParens": "always",
"printWidth": 100,
"semi": true,
"bracketSpacing": true
}
Посмотреть значение доступных правил можно в документации. WebStrom после создания файла конфигурации сама предложит использовать prettier
при запуске форматирования через IDE. Чтобы форматирование не тратило время впустую, добавим в исключения каталог /node_modules
и /dist
с помощью файла .prettierignore
(формат аналогичен .gitignore
). Теперь можно запустить prettier
, применив правила форматирования к исходному коду:
prettier --write "**/*"
Чтобы не запускать команду явно каждый раз руками и быть уверенным, что код остальных разработчиков проекта также будет отформатирован prettier
, добавим запуск prettier
на precommit-hook
для файлов, отмеченных как staged
(через git add
). Для такого дела нам нужно два инструмента. Во-перых — это hasky, ответсвенного за выполнение каких-либо команд перед коммитом, пушем и т.п. А во-вторых — это lint-staged, который может запускать разные линтеры на staged
файлы. Нам нужно выполнить всего лишь одну строчку, чтобы поставить эти пакеты и добавить команды запуска в package.json
:
npx mrm lint-staged
Мы можем не ждать форматирования до коммита, а сделать так, чтобы prettier
постоянно срабатывал на изменённые файлы в процессе нашей работы. Да, нам нужен ещё один пакет — onchange. Он позволяет следить за изменениями файлов в проекте и тут же выполнять необходимую для них команду. Устанавливаем:
npm install --save-dev --save-exact onchange
Затем в команды поля scripts
в package.json
добавляем:
"prettier-watch": "onchange 'src/**/*' -- prettier --write {{changed}}"
На этом все споры о форматирвании в проекте можно считать закрытыми.
Избегаем ошибок с ESLint
ESLint уже давно стал стандартом и его можно встретить практически во всех js и ts-проектах. Нам он тоже поможет. В конфигурировании ESLint я доверяю CRA, поэтому просто возьмём необходимые пакеты из CRA и подключим в нашу библиотеку. Кроме того, добавим конфиги для TS и prettier
(чтобы избежать конфликтов между ESLint
и prettier
):
npm install --save-dev eslint eslint-config-react-app eslint-loader eslint-plugin-flowtype eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser babel-eslint eslint-config-prettier eslint-plugin-prettier
Настроим ESLint
с помощью конфигурационного файла.
{
"extends": [
"plugin:@typescript-eslint/recommended",
"react-app",
"prettier",
"prettier/@typescript-eslint"
],
"plugins": [
"@typescript-eslint",
"react"
],
"rules": {
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-member-accessibility": "off"
}
}
Добавим в поле scripts
из package.json
команду lint
— eslint src/**/* --ext .ts,.tsx --fix
. Теперь можно запустить eslint через npm run lint
.
Тестируем с Jest
Чтобы писать модульные тесты для компонентов библиотеки, установим и сконфигурируем Jest — библиотеку тестирования от facebook. Однако, т.к. мы компилируем TS не через babel 7, а через tsc, то нам нужно также установить пакет ts-jest:
npm install --save-dev jest ts-jest @types/jest
Чтобы jest нормально воспринимал импорты css или других файлов, необходимо подменить их моками. Создаём каталог __mocks__
и создаём там два файла.
styleMock.ts
:
module.exports = {};
fileMock.ts
:
module.exports = 'test-file-stub';
Теперь создаём конфиг jest.
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleNameMapper: {
'\\.(css|less|sass|scss)$': '<rootDir>/__mocks__/styleMock.ts',
'\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.ts'
}
};
Напишем простейший тест для нашего ExampleComponent
в его каталоге.
import { ExampleComponent } from './ExampleComponent';
describe('ExampleComponent', () => {
it('is truthy', () => {
expect(ExampleComponent).toBeTruthy();
});
});
Добавим в поле scripts
из package.json
команду test
— npm run lint && jest
. Для надёжности ещё и прогоним линтер. Теперь можно запустить наши тесты и удостовериться, что они проходят — npm run test
. А чтобы при сборке тесты не попали в dist
, добавим в конфиге Rollup
плагину typescritp
поле exclude
— ['src/**/*.test.(tsx|ts)']
. Укажем запуск тестов в husky pre-commit hook
перед запуском lint-staged
— "pre-commit": "npm run test && lint-staged"
.
Разрабатываем, документируем и любуемся компонентами с Storybook
Каждая библиотека нуждается в хорошей документации для её успешного и продуктивного использвания. Что касается библиотеки компонентов интерфейса, то про них не только хочется прочитать, но и посмотреть как они выглядят, а лучше всего потрогать и поизменять. Для поддержки такой хотелки есть несколько решений. Раньше я использовал Styleguidist. Этот пакет позволяет писать документацию в формате markdown, а также вставлять в неё примеры описываемых React-компонентов. Далее документация собирается и из неё получается сайт-витрина-каталог, где можно найти компонент, прочитать документацию о нём, узнать о его параметрах, а также потыкать в него палочкой.
Однако в этот раз я решил присмотреться к его конкуренту — Storybook. На сегодняшний момент он кажется более мощным с его системой плагинов. Кроме того, он постоянно развивается, имеет большое сообщество и скоро также начнёт генерировать свои страницы документации с помощью markdown-файлов. Ещё одно достоинство Storybook это то, что он является песочницей — средой для изолированной разработки компонентов. Это означает, что нам не нужны никакие полноценные приложения-примеры для разработки компонентов (как это предлагает CRL). В storybook мы пишем stories
— ts-файлы, в которых мы передаём наши компоненты с некоторыми входыми props
в специальные функции (лучше посмотреть на код, чтобы стало понятнее). В итоге из этих stories
собирается приложение-витрина.
Запустим скрипт, который выполнит инициализацию storybook:
npx -p @storybook/cli sb init
Теперь подружим его с TS. Для этого нам нужно ещё немного пакетов, а заодно поставим пару полезных аддонов:
npm install --save-dev awesome-typescript-loader @types/storybook__react @storybook/addon-info react-docgen-typescript-loader @storybook/addon-actions @storybook/addon-knobs @types/storybook__addon-info @types/storybook__addon-knobs webpack-blocks
Скрипт создал каталог с конфигурацией storybook
— .storybook
и каталог с примером, который мы безжалостно удаляем. А в каталоге конфигураций меняем расширение addons
и config
на ts
. В файл addons.ts
подключим аддоны:
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import '@storybook/addon-knobs/register';
Теперь, надо помочь storybook с помощью конфига webpack в каталоге .storybook
.
module.exports = ({ config }) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve('awesome-typescript-loader')
},
// Optional
{
loader: require.resolve('react-docgen-typescript-loader')
}
]
});
config.resolve.extensions.push('.ts', '.tsx');
return config;
};
Немного подправим конфиг config.ts
, добавив декораторы для подключения аддонов ко всем нашим stories.
import { configure } from '@storybook/react';
import { addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import { withKnobs } from '@storybook/addon-knobs';
// automatically import all files ending in *.stories.tsx
const req = require.context('../src', true, /\.stories\.tsx$/);
function loadStories() {
req.keys().forEach(req);
}
configure(loadStories, module);
addDecorator(withInfo);
addDecorator(withKnobs);
Напишем нашу первую story
в каталоге компонента ExampleComponent
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { ExampleComponent } from './ExampleComponent';
import { text } from '@storybook/addon-knobs/react';
const stories = storiesOf('ExampleComponent', module);
stories.add('ExampleComponent', () => <ExampleComponent text={text('text', 'Some text')} />, {
info: { inline: true },
text: `
### Notes
Simple example component
### Usage
~~~js
<ExampleComponent
text="Some text"
/>
~~~
`
});
Мы использовали аддоны:
Теперь обратим внимание, что скрипт инициализации storybook добавил к нам в package.json
команду storybook
. Воспользуемся ей для запуска npm run storybook
. Storybook соберётся и запустится по адресу http://localhost:6006
. Не забудем таже добавить в исключение для модуля typescript
в конфиге Rollup
— 'src/**/*.stories.tsx'
.
Разрабатываем
Итак, окружив себя множеством удобных инстументов и приготових их к работе, можно приступить к разработке новых компонентов. Каждый компонент будем помещать в свой каталог в src/components
с названием компонента. В нём будут находится все связанные с ним файлы — css, сам компонент в tsx-файле, тесты, stories. Запускаем storybook, создаём для компонента stories, там же пишем к нему документацию. Создаём тесты и тестируем. Импорт-экспорт готового компонента записываем в index.ts
.
Кроме того, можно авторизоваться в npm
и опубликовать свою библиотеку как новый npm-пакет. А можно подключать её прямо из git-репозитория как из master, так и из других веток. Например, для моей заготовки можно выполнить:
npm i -s git+https://github.com/jmorozov/react-library-example.git
Чтобы в приложении-потребителе библиотеки в каталоге node_modules
было только содержимое каталога dist
в собранном состоянии, необходимо добавить в поле scripts
команду "prepare": "npm run build"
.
Также, благодаря TS, будет работать автодополнение в IDE.
Подводим итоги
В середине 2019 года можно довольно быстро начать разрабатывать свою библиотеку компонентов на React и TypeScript, пользуясь удобными инструментами разработки. Этого результата можно достичь как с помощью автоматизированной утилиты, так и в ручном режиме. Второй путь является предпочтительным, если нужны актуальные пакеты и больше контроля. Главно знать куда копать, а с помощью примера в этой статье, я надюсь, это стало несколько проще.
Вы также можете взять получившуюся заготовку тут.
Кроме всего прочего, я не претендую на истину в последней инстанции и, вообще, занимаюсь фронтендом постольку-поскольку. Вы можете выбрать альтернативные пакеты и опции конфигурации и также достичь успеха в создании своей библиотеки компонентов. Буду рад, если вы поделитесь в комментариях своими рецептами. Happy coding!
Комментарии (10)
pawlo16
26.07.2019 19:29Любезный, а чего ради эта гимнастика с ручным созданием проекта, если добрые умные дяди из фейсбука давно уже придумали сreacte-react-app c typescript-ом и всем всем всем? И зачем babel для транспиляции в ES5, если typescript с этим прекрасно справляется?
frozen_coder Автор
27.07.2019 21:14При должной сноровке и опыте, я не сомневаюсь, что можно и из CRA стартовать библиотеку. Кстати, CRL базируется на CRA — тянет за собой react-scripts-ts, который в свою очередь основан на react-scripts, правда старой версии. Я попробовал перетащить это на последний react-scripts и не смог натянуть сову на глобус. Пришлось распотрошить и собрать сову самостоятельно.
Далее. Существует 2 способа перегнать TS в ES5 — tsc и babel 7. CRA, CRL и tsdx используют именно последний. А babel 7 в свою очередь имеет ряд ограничений для такой задачи, что не слишком круто, но и не фатально в общем случае. Это влечёт за собой обязательную опцию компилятора — isolatedModules, которая в свою очередь не хочет работать вместе с declaration-опцией, а мне таки хотелось генерировать `d.ts`. Вот тут предлагают использовать 2 конфига, но что-то у меня рука тянется к лицу от этого.
Про свои неудачи я написал под спойлером «А потом что-то пошло не так...».
Также в той заготовке, что я сделал руками, не используется babel для сборки TS. Однако, да, он есть в devDependencies. Это из-за `webpack-blocks` (говорит есть в его peerDependecies, хочу его, не могу), который в свою очередь используется в `webpack.config.js`. Что? Webpack? У нас же вроде Rollup. Ага. Для самой библиотеки Rollup, вот только StoryBook не может сам без конфига для своего внутреннего webpack работать с TS-компонентами. Такие дела. Может быть можно и проще, но я пока не вижу больших проблем от этого — это же devDependencies, к пользователям эта орава не поедет.ua9msn
29.07.2019 20:36Это из-за `webpack-blocks`
Не только. @storybook/addon-info тоже его хочет. Точнее не совсем он, а react-docgen-typescript-loader, для которого он собственно и нужен.
Плюс, если лень конфигурить ts для storybook врукопашную — у них есть preset. Но он тоже весьма капризен и очень хочет ts-loader как загрузчик, другое кушать не желает. Зоопарк лоадеров. Слегка раздражает.
Ну, и если можно, вопрос к вам, не могу понять, все обновляется при любых изменениях компонента кроме jsDoc описания. Обновляется только после полного перезапуска storybook. Не сталкивались ли?
hk-fellow
27.07.2019 08:41Спасибо за стаью и код! Извиняюсь, если вопрос глупый, но зачем вобще писать свою библиотеку, почему не воспользоваться каким-нибудь material-ui, ant?
MaZaAa
27.07.2019 08:54Если бы вы были именно программистом, а не так чисто только ради денег в этой отрасли, то вы бы не задавали этот реально глупый вопрос.
hk-fellow
27.07.2019 09:14Вобще-то в отрасли меня еще нет, я безработный)) Только мечтаю в нее попасть)) Я в курсе, что «единственный способ выучить новый язык программирования — писать на нем программы», и что хорошие разработчики часто имеют собственные pet-проекты, на которых можно пробовать всякие новые инструменты и идеи без риска сломать продакшен или затянуть сроки, без давления со стороны всяких менеджеров-тимлидов-заказчиков.
Но автор написал «появилась задача начать библиотеку компонентов на React» — звучит будто ему поставил такую задачу заказчик, и он ее будет выполнять именно ради денег.
kuftachev
30.07.2019 11:13Если Вы были бы реально программистом, то Вы бы понимали пользу от готовых общепринятых решений и не писали бы свои велосипеды без повода!
frozen_coder Автор
27.07.2019 09:02Пожалуйста.
По возможности лучше, конечно же, не писать, а взять готовое. Мне, например, нравится ещё semantic-ui.
Но бывает, что готовое не подходит, нужны свои стили или сверстать компонент по-другому, свои компоненты со своими фичами, и тогда готовое может не подойти.
В моём случае у нас есть некий шаблон со своими стилями и вёрсткой, который используется в нескольких системах и все они выглядят единообразно. Автор шаблона его забросил. Мы использовали его под Angular.js. Новые системы мы будем писать на React + мигрируем некоторые старые, а стили менять не хотим, чтобы сохранить единообразие и вообще мигрировать постепенно и незаметно для пользователя. Из этих требований и рождается наша библиотека компонентов на React. Благо мне верстать и писать css не надо (по минимуму), просто компонентов напилить, а ещё можно подсматривать в готовые бибилотеки.
Если посмотреть на опыт других компаний, то много кто пишет свой UI-kit. Навскидку JetBrains, Яндекс, Тинькоф, Сбербанк — правда, у этих ребят толпы разработчиков, отдельные команды под это, могут себе позволить.
StanEgo
Или, как вариант, одна строка и rollup, jest, etc под капотом:
frozen_coder Автор
Хороший вариант, спасибо. Дополнил статью. Есть недостаток — не нашёл способов как-нибудь расширить конфигурацию или сделать eject. Про это есть issue. Конечно, зависит от проекта. Для многих это может быть не критично.