@neoflex/fastdata-ui-kit v0.20.6
Библиотека компонентов DesignSystem UI
Проект совмещает библиотеку, сторибук, и CRA приложение consumer. В процессе разработки компонентов, даёт возможность
напрямую отображать их в сторибуке или CRA, минуя бандлинг. Предполагается наличие yarn
, или npm
установленных глобально.
Общие сведения
Библиотека
Бандл библиотеки публикуется в git-репозиторий https://neogit.neoflex.ru/fastdata/fastdata-ui-kit. Каждая опубликованная
версия представляет собой один коммит в ветке master
. Номер версии бандла (такой, как 0.2.2
) сохраняется в сообщение
коммита, в файл package.json
, и в легковесный тег, которым помечается коммит. Сохранение версии в теге позволяет
consumer'ам использовать фиксированную версию бандла:
npm i @neoflex/fastdata-ui-kit@latest --save
.
Если пакет добавляется без указания версии (#0.2.2
), будет использоваться последняя опубликованная версия.
Точка входа бандлера - src/components/index.js
. Всё что экспортируется в этом файле, попадает в бандл, и будет
доступно consumer'ам через import { ... } from '@neoflex/fastdata-ui-kit'
.
Репозиторий с бандлом хранится в каталоге lib-build
(будет склонирован при первом билде бандла), и используется для
публикации новых версий.
npm-скрипты билдинга/публикации:
yarn lib-build
- собирает бандл из исходников. Сейчас это один файл -index.js
. Предварительно клонирует (или обновляет, git pull) репозиторий в каталогеlib-build
. В итоге получаем свежий репозиторий с перезаписанным файломlib-build/index.js
yarn lib-publish
- коммитит и пушит бандл (если в нём есть изменения). Принимает параметром номер публикуемой версии. Если параметр не указан, запросит номер версии в консоли, предлагая в качестве значения по-умолчанию, номер
предыдущей версии увеличенный на0.0.1
yarn lib-bp
- последовательно выполнит скриптыlib-build
иlib-publish
. Как иlib-publish
, может принимать параметром номер версии
yarn lib-rollup
- только собирает бандлlib-build/index.js
, без предварительной подготовки репозитория в каталогеlib-build
. Удобно использовать при отладке бандлинга. Также используется командойlib-build
Сторибук
Сторибук визуализирует для каждого компонента JSX, возвращаемый одной или более story - функциями принимающими
args от сторибука, и рендерящими некоторым образом компонент. Поиск stories производится в файлах
src/**/*.stories.js
. Каждый именованный экспорт в таком файле описывает одну story, а export default
задаёт доп.
параметры для stories в файле.
npm-скрипты:
yarn story
- запускает dev режим сторибука
yarn build-storybook
- собирает бандл сторибука в каталогstorybook-static
CRA приложение consumer
Содержится в каталоге src/cra
, точка входа - src/cra/index.js
.
npm-скрипты:
yarn start
- запускает dev режим приложения
yarn build
- собирает бандл приложения в каталогbuild
Сторибук и CRA импортируют компоненты библиотеки через файл src/config/library_proxy.js
, который используется для
переключения между режимом использования исходников компонентов напрямую из src/components/index.js
,
и режимом использования бандла node_modules/@neoflex/fastdata-ui-kit
. Переключение между этими режимами можно
производить с помощью npm-скриптов yarn set-dev-conf
и yarn set-build-conf
.
На текущий момент, режим использования бандла работает только с CRA. Сторибук перестал работать в этом режиме после добавления одной оптимизации бандлинга, необходимой для работы tree shaking'a (см. ниже). Почти наверняка это можно починить.
Темизация
Библиотека поддерживает темизацию на основе SCSS переменных. Данные тем описываются файлами src/scss/themes/_*.scss
.
Эти файлы, помимо темизируемых значений CSS-свойств, могут содержать значения любых типов данных SCSS, используемые
в SCSS-модулях компонентов. Всегда должен присутствовать файл дефолтной темы _default.scss
. Остальные темы могут
описывать только отличия от дефолтной (или любой другой) темы, ссылаясь на имя родительской темы в поле parent.
В объектах (мапах) тем предусмотрен особый объект globals, предназначенный для описания глобальных переменных темы.
На значения globals-переменных можно ссылаться из других переменных (определяемых в данной теме, или в её потомках):
$default: (
globals: (
color-text-primary: $gray-9,
...
),
typography: (
colors: (
primary: _color-text-primary, // ссылка должна начинаться с символа _
...
),
...
),
...
);
\
Стили компонентов должны писаться так, как если бы описывали какую-то одну тему, например дефолтную. Для доступа к
значениям, определяемым в файлах тем, SCSS-модули компонентов могут использовать функцию get
определённую в файле
src/scss/_themes_builder.scss
(вручную импортировать этот файл не нужно). Для генерации стилей всех тем, SCSS-модули
всех компонентов будут использоваться несколько раз подряд, столько, сколько генерируется тем, при этом функция get
всякий раз будет возвращать значения текущей генерируемой темы. Все селекторы находящиеся на самом верхнем уровне
SCSS-модуля (не вложенные в другие конструкции) будут автоматически конкатенироваться с классом текущей темы, вида
.theme-magenta
(не считая дефолтной темы; можно считать что доп. класс дефолтной темы является пустой строкой).
Остальные селекторы (не находящиеся на самом верхнем уровне), останутся без изменений. При необходимости темизировать
такие селекторы, можно воспользоваться переменной $curThemeClass
из файла _themes_builder.scss
, подобным образом:
@mixin icons($opacities) {
@for $i from 1 through 3 {
#{$curThemeClass}.icon#{nth($states, $i)} {
opacity: nth(get(component opacities), $i);
}
}
}
\
Следует учитывать что значением $curThemeClass
при генерации дефолтной темы, будет пустая строка. Т.е. код
использующий данную переменную должен быть к этому готов. Автоматическую темизацию селекторов верхнего уровня можно
отключать с помощью комментария // custom
, размещённого внутри блока, следующего за селектором:
.selector { // custom
...
}
\
JavaScript компонента должен сам позаботиться о назначении класса темы DOM-элементам (название темы он может
получить с помощью хука useTheme
экспортируемого файлом src/components/Theme.js
). В случае если вложенность
селекторов в файле стилей повторяет вложенность DOM-элементов компонента, и используется автоматическая темизация
селекторов, достаточно будет назначить класс темы только одному внешнему DOM-элементу, подобным образом (см. также
компоненты Radio
и Button
):
const theme = useTheme();
return (
<button
className={classNames(
theme && css[`theme-${theme}`],
otherClass,
...
)}
>
...
</button>
);
\
Для задания темы компонентам, consumer'ам предлагается использовать компонент ThemeProvider
из файла
src/components/Theme.js
, передающий вложенным в него компонентам библиотеки название темы через контекст:
<ThemeProvider theme="magenta">
...
<div>
...
<Button {...args} />
...
</div>
...
</ThemeProvider>
\ Для использования одной лишь дефолтной темы, наличие выше по дереву компонента ThemeProvider необязательно.
Список включаемых в бандл тем задаётся массивом themes
в корневом package.json
.
Механизм темизации использует кастомный процессинг SCSS-файлов: генерируются темизированные версии SCSS для всех тем компонента как описано выше, далее они по отдельности рендерятся в CSS с помощью стандартного SASS-препроцессора, затем из полученных фрагментов CSS каждой темы удаляются декларации, дублирующие декларации соответствующих селекторов дефолтной темы, и наконец оставшийся CSS объединяется. Удаление избыточных деклараций позволяет заметно сократить размер бандла.
Для просмотра итогового CSS компонента, можно прописать его имя в массиве saveCssFilePatterns
в файле
src/build-utils/webpack-scss-loader.js
. При работе сторибука или CRA, CSS-файл такого компонента будет сохраняться
по соседству с SCSS файлом. Для временного отключения кастомного процессинга SCSS-модуля (например в отладочных
целях), можно в первой строке модуля разместить коммент // skipTheming
.
Если библиотека будет собираться только с единственной дефолтной темой, кастомный процессинг SCSS не должен создавать
бо́льшую вычислительную нагрузку чем стандартный. Если всё же потребуется его отключить, сделать это можно в файлах
src/build-utils/webpackFinal.js
, для сторибука/CRA, и rollup.config.js
для бандла (в rollup.config.js
нужно будет
заменить use: ['scss-custom-loader']
на use: ['sass']
). Компоненты импортирующие файл стилей src/scss/_core.scss
не будут ломать сборку библиотеки после отключения кастомного процессинга, т.к. в этом файле определены переменная
$curThemeClass
и облегчённая версия функции get
, обеспечивающие правильную генерацию дефолтной темы.
Бандлинг
Tree Shaking
Tree Shaking - механизм используемый вебпаком для удаления из бандла проекта неиспользуемого кода. Библиотека совместима с данным механизмом. Для обеспечения его работы в приложениях-consumer'ах, используются следующие средства:
- бандл создаётся в формате ESM (ECMAScript modules), этим обеспечивается tree shaking JS кода;
- стили инжектятся в JS бандла с помощью
rollup-plugin-styles
, умеющего делать их tree shaking совместимыми; - используется
babel-plugin-pure-static-props
для поддержки tree shaking'а функц. компонентов имеющихpropTypes
иdefaultProps
.
Проблема с tree shaking'ом функц. компонентов, имеющимх propTypes
и defaultProps
описана здесь
и здесь.
Вообще говоря, если использовать только propTypes
(без defaultProps
), то проблемы не будет. Механизм перестаёт
корректно работать при наличии двух и более присваиваний свойств объекту-функции компонента.
babel-plugin-pure-static-props
решает эту проблему оборачивая компонент внутри бандла в IIFE:
const Typography = /*#__PURE__*/function () {
const Typography = function Typography(props) { ... };
Typography.propTypes = { ... };
Typography.defaultProps = { ... };
return Typography;
}();
\ Именно эта манипуляция приводит к отказу сторибука работать с компонентами из бандла, однако поддержка библиотекой tree shaking'а видится более весомой.
Подобная проблема существует и у классовых компонентов, и решить её можно с помощью
babel-plugin-no-side-effect-class-properties
. defaultProps
для функц. компонентов в будущем, вероятно станет
deprecated (https://twitter.com/dan_abramov/status/1133878326358171650). В нашей библиотеке propTypes
и
defaultProps
используются из-за требований сторибука. Если поддержка сторибука не нужна, но нужен tree shaking,
вероятно, лучше не использовать defaultProps
. Тогда можно будет отключить babel-plugin-pure-static-props
.
Scoped CSS Classnames
Для уменьшения размера бандла, имена CSS классов заменяются в нём на короткие уникальные хэши. Для формированиия
такого хэша используется имя SCSS файла компонента объединённое с исходным именем CSS класса. Функция формирующая хэш
определена в файле rollup.config.js
(generateScopedName
). Может быть модифицирована: например, если компонентов в
библиотеке станет много и потребуется увеличить уникальность хэшей.
Возможные ошибки
Иногда при установке пакетов может упасть ошибка.В этом случае рекомендуется переименовать файл .npmrc и запустить установку снова.
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago