8.0 KiB
@tnsu/ui-kit — память проекта
Единый пакет UI-компонентов для SPFx web part'ов ТНСУ + Storybook как витрина. Этот файл — источник правды по решениям, плану и прогрессу. Обновлять по ходу работы.
Зачем проект
У команды много SPFx web part'ов в разных репозиториях (request-portal, бывший
1c-ticket-form, pto-tracker и др.). В каждом дизайн разъезжается, компоненты копируются
и пишутся заново. Цель — вынести компоненты в один npm-пакет, подключать его в любую
web part через npm i, и держать единый вид через дизайн-токены.
Источник компонентов: request-portal/src/webparts/requestPortal/shared/ui/ — там уже
~30 чистых компонентов на SCSS-модулях с barrel-экспортом (ui/index.ts). Это база.
Ключевые архитектурные решения
- Гибридный подход: отдельный репозиторий
tnsu-ui-kit(пакет + Storybook), публикуется в GitLab Package Registry. Существующие web part'ы остаются в своих репах и просто ставят пакет. НЕ монорепо (не хотим переселять существующие проекты). - Сборка — Vite (library mode), не tsup. Причина: компоненты на
.module.scss, Vite понимает SCSS-модули из коробки и он же движок Storybook → один инструмент. - React/Fluent/tslib — только
peerDependencies(React 17, @fluentui/react 8, tslib). Защита от двух React в бандле («Invalid hook call»). Локально те же версии стоят как devDependencies для сборки и Storybook. - Дизайн-токены (
tokens.scss: цвета, отступы, радиусы) — единый рычаг общего вида. Компоненты тянут значения оттуда, а не хардкодят. - Скоуп имени
@tnsu— сверить с именем группы в GitLab на шаге публикации. Пока имя ни на что не влияет, переименование = find-replace. - Что переносим: только чистые UI-примитивы (Button, TextInput, FormCard, Select,
ItemsTable, PeopleField...). НЕ переносим бизнес-логику:
approval/,pnp/,dictionary/, сервисы SharePoint — они привязаны к спискам. Возможно позже отдельный пакет@tnsu/sp-core. - Расширение через пропсы, не форки. Если в старом проекте компонент выглядел иначе —
добавляем
variant/sizeв ui-kit, а не плодим копии. - Версии инструментов синхронны с SPFx: TypeScript пинить на
~5.8.0(как в request-portal). Без пинаnpm i typescriptставит TS 7 (нативный компилятор без JS Compiler API) — vite-plugin-dts падает. То же правило для React/Fluent.
План (маршрут)
- Скелет репо — папка, git, package.json, зависимости
- Сборка (Vite) — vite.config.ts, пакет собирается в dist/
- Первый компонент — Button перенесён, сборка чистая
- Дизайн-токены — src/tokens/_tokens.scss перенесён из request-portal
- Storybook — витрина работает (SB 10.4 + Vite), Button виден со всеми вариантами
- Публикация — @tnsu/ui-kit@0.0.1 опубликован в Gitea (это Gitea 1.26.4, НЕ GitLab!)
- [~] Потребление проверено ПОЛНОСТЬЮ: request-portal собрался (heft webpack ок) + кнопки из пакета отрисовались в SharePoint workbench со стилями (accent-золото, secondary-рамки). CSS из пакета применяется в рантайме. Осталась публикация в registry.
ВАЖНО про потребление (проверено 2026-08-13):
- Тест через локальный тарбол (
npm pack→npm i ../tnsu-ui-kit/*.tgz), НЕ npm link (link тащит второй React → Invalid hook call). - CSS подключается в SPFx через
import '@tnsu/ui-kit/styles.css'в корневом компоненте веб-парта (RequestPortal.tsx). SPFx-webpack (5.95) обрабатывает .css из node_modules — ОК. - Заменён Button в SubmitActions.tsx (
../Button/Button→@tnsu/ui-kit). Правки НЕ коммитить, пока пакет не опубликован в registry (сейчас ссылается на file:-тарбол).
Известный tech-debt: Sass @import устарел (Dart Sass 3.0). Мигрировать токены и
модули на @use/@forward — отдельной задачей, сейчас работает с варнингом.
Прогресс / журнал
- Шаг 1 готов: создан репо
C:\Users\gorodetskiy.timur\Documents\Projects\tnsu-ui-kit,git init, болванка package.json. - Шаг 2 в работе: переписан package.json (@tnsu/ui-kit, exports, peerDeps, Vite-скрипты), ставятся devDependencies, добавлен .gitignore.
Как мигрировать старый проект (памятка на будущее)
npm i @tnsu/ui-kit— ничего не ломается, пакет просто лежит рядом.- Заменяем импорты по одному компоненту/форме:
../shared/ui→@tnsu/ui-kit. Пропсы те же, JSX не меняется. Старый и новый компонент могут сосуществовать. - Проверили форму → удалили старый компонент из
shared/ui. - Повторяем, пока
shared/uiне опустеет. - Перед миграцией проекта проверить: его версии React/Fluent совместимы с peerDeps ui-kit.
Публикация (Gitea, НЕ GitLab!)
- Хостинг git — Gitea 1.26.4 на http://git.tnsu.kz (не GitLab). Registry npm привязан к ВЛАДЕЛЬЦУ, не к проекту. Никакого "project ID" не нужно.
- Адрес registry:
http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/ .npmrcв проекте (можно коммитить, НЕ секрет):@tnsu:registry=http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/- Токен (СЕКРЕТ) — в
~/.npmrc(C:\Users\gorodetskiy.timur.npmrc), в git НЕ попадает://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/:_authToken=<TOKEN> - Токен создаётся в Gitea: аватар → Настройки → Приложения → права
package= Чтение и запись. - Публикация:
npm run build && npm publish. Бамп версии в package.json перед каждой публикацией (npm не даёт перезаписать уже опубликованную версию). - Потребителю (request-portal и др.) нужен такой же
@tnsu:registryв его.npmrc+ свой токен на чтение пакетов.
Окружение
- Node: v22.x (как в SPFx: >=22.14 <23)
- React 17.0.1, @fluentui/react ^8.106.4, tslib 2.3.1
- GitLab: http://git.tnsu.kz/timur.gorodetskiy/tnsu-ui-kit.git