Rambler UI
Опыт разработки кросспроектной библиотеки
компонентов на React.JS
дратути
- Общий профиль пользователя ID Rambler&Co
- Админки: CRM, Комментарии, Опросы
- Виджеты: Комментарии, Опросы/Квизы, Платежка, Соц. шарилка

Сергей Перескоков, frontend
Платформa Rambler&Co - кросспроектные сервисы
Какую проблему ты пытаешься решить?

- Переиспользование верстки
- Переиспользование js-кода контролов
- Одинаковый дизайн на всех проектах
- Простой старт новых проектов
- Одинаковый дизайн на всех сервисах
- Code-reuse
- Не нужно верстать и программировать контролы
- Автообновление дизайна
- Разделение разработки на продуктовую и интерфейсную
🛠 Компонентный подход
Соберем требования
-
Поддержка React.js
-
🔞 Соблюдение наших design-guides
-
Простая установка для webpack/browserify
-
Желательно через npm/yarn
-
Поддержка тем (нескольких и в рантайм)
-
Поддержка модульности (только нужные CSS и JS)

6 years ago
Twitter Bootstrap
- Since 2011
- Готовая верстка (forms, modals, grid, etc.)
- Возможность кастомизации (LESS/SASS или 💩хардкод)
- Интеграция с JQuery
- Прекрасный сайт с документацией
- Набор элементов и API почти не меняется
- Есть библиотека для React
Bootstrap Skin?
- ✅ Есть готовые компоненты на React.js
- ✅ Настройка тем при сборке (через LESS переменные)
- ⚠️ Global-scoped CSS
- ⚠️ Переписывание и дополнение CSS-стилей при рескине не надежно, т.к. это не API для кастомизации
- ⛔️ Не все состояния из design-guides есть в bootstrap
- ⛔️ Монолитный CSS для react-библиотеки
- ⛔️ Нет поддержки нескольких тем и тем в рантайме
Bootstrap Skin?

Google Material Design
- Since 2014
- Design guides прежде всего
- Mobile-first
- Компонентный подход
- Оф. реализация на Angular
- Есть рескины bootstrap (WTF?!)
- material-ui.com на React.js
Material Design Reuse
- ✅ Реализация на React.js
- ✅ Модульный подход
- ✅ Использование тем в рантайм
- ✅ Строгий API для кастомизации
- ⛔️ Не все наши design-guides переносятся в набор компонент material-ui
Google Material Design

Делаем свою библиотеку

Button Component
- JS
- HTML (JSX)
- CSS
- Props
- Theme
- Documentation
- Examples
- Tests
import Button from 'rambler-ui/Button'
class MyComponent extends React.Component {
render() {
return <div><Button>Hello</Button></div>
}
}
CSS

- Препроцессоры + компиляция .css
- Препроцессоры + сборка у пользователя .sass/.less/.styl
- 👊 CSS in JS
CSS in JS
Стили создаются в рантайме и добавляются в документ через тег <style> или атрибут style="..."

CSS in JS - решения
- props.style
- Radium
- StyledComponents
- JSS
Inline Styles
- Поддержка ReactNative
- Работают быстрее
<Style> tag
- Привычные селекторы
- Поддержка псевдоклассов
- Специфичность селектора - css-класс
✅
StyledComponents
- Тег + CSS-класс = <Component>
- <Style> остается в DOM навсегда
- Поддержка ReactNative
const Button = styled.button`
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
${props => props.primary && css`
background: palevioletred;
color: white;
`}
`
render(
<div>
<Button>Normal Button</Button>
<Button primary>Primary Button</Button>
</div>
)
JSS
- Привычные CSS-классы
- Поддержка JS-object кода (легко писать миксины)
- Тег <style> добавляется в дерево при маунте компонента и удаляется при анмаунте
- Если на странице несколько инстансов одного и то же компонента с одной и той же темой, <style> будет добавлен один раз
JSS + themed-react-jss
@injectSheet((theme) => ({
container: {
display: 'inline-block',
fontSize: 12,
color: theme.button.fontColor,
background: theme.button.backgroundColor
},
icon: {
paddingRight: 15
}
}))
class Button extends Component {
render() {
const css = this.props.sheet.classes
return <div className={css.container}>
<Icon className={css.icon} />
{this.props.children}
</div>
}
}
render(
<ApplyTheme theme={{button: {fontColor: '#fff', backgroundColor: '#000'}}}>
<Button>Hello<Button>
</ApplyTheme>
)
Поддержка нескольких тем
render(
<div>
<ApplyTheme theme={{button: {fontColor: '#fff', backgroundColor: '#000'}}}>
<ApplyTheme theme={{button: {fontColor: 'yellow'}}}>
<Button>Hello<Button>
</ApplyTheme>
<ApplyTheme theme={{button: {backgroundColor: 'blue'}}}>
<Button>Hello<Button>
</ApplyTheme>
</ApplyTheme>
</div>
)
StyledComponents
✅ JSS
Требования к документации
- Мультиверсионность
- Возможность редактировать код
- Скопированный код будет сразу работать
- Таблица со свойствами компонента
- Кастомное дерево компонентов
- Кастомизация сайта с документацией
- Полноценная песочница
React StyleGuidist
React StyleGuidist
- Нет полноценной песочницы
- Все компоненты выводятся сразу (тормозит)

Делаем свою документацию
-
react-docgen
-
codemirror
-
( highlight.js )
Делаем свою документацию
import React from 'react'
import Avatar from 'rambler-ui/Avatar'
import { ApplyTheme } from 'rambler-ui/theme'
export default function AvatarExample() {
const props = {
style: {
marginLeft: 10
},
src: '//api.adorable.io/avatars/face/eyes4/nose5/mouth7/8e8895/'
}
return (
<div>
<ApplyTheme>
<div>
<div style={{ display: 'inline-block', width: '33%' }}>
Circle
<Avatar {...props} profileType="facebook" />
<Avatar {...props} size={20} />
<Avatar {...props} size={60} />
</div>
</div>
</ApplyTheme>
</div>
)
}
DEMO
git.io/rambler-ui
Profit.
RamblerUI используется в проектах:
- Комментарии
- CRM
- QUIZ
- Профиль пользователя ID Rambler&Co
- Рамблер/Почта
Что дальше?
- Покрытие тестами
- Расширение набора компонент
- Налаживание процессов разработки
- Дистрибуция 🚀
✌️Спасибо.
Список ресурсов и баззвордов:
- JSS
- StyledComponents
- themed-react-jss
- rambler-ui
deck
By Sergey Pereskokov
deck
- 993