Совместное использование восьмиэтапной миграции с несколькими сборниками рассказов в монорепозитории
Введение
Storybook — инструмент для разработки пользовательского интерфейса. Это делает разработку быстрее и проще за счет изоляции компонентов. Это позволяет нам работать над одним компонентом за раз. Он упрощает разработку, тестирование и документирование пользовательского интерфейса.
Сборник рассказов 7 был выпущен 3 апреля 2023 года. Это первый крупный выпуск за более чем два года и, безусловно, самый крупный за всю историю. Он приносит много возможностей:
- Первоклассная поддержка Vite
- Поддержка нулевой конфигурации для NextJS и SvelteKit на базе API новых фреймворков.
- Component Story Format 3 (CSF3) с улучшенной безопасностью типов
- Поддержка MDX2 и оптимизированные блоки документов
- Обновление дизайна пользовательского интерфейса
- Улучшенное тестирование взаимодействия и тестовое покрытие
- Экосистема CI для повышения стабильности и более плавного обновления
Задание
Мы были на Storybook 6, используя React и Webpack, с тремя сборниками рассказов, определенными в монорепозитории, стратегии разработки программного обеспечения, в которой код для нескольких проектов хранится в одном репозитории.
root ├── .storybook │ ├── main.js │ └── preview.jsx ├── node_modules ├── package.json ├── components │ ├── .storybook │ │ ├── main.js │ │ ├── preview.jsx │ │ └── style.css │ └── package.json └── apps ├── .storybook │ ├── main.js │ └── preview.jsx └── package.json
- Репозиторий имеет
root
, где определяется глобальныйpackage.json
и генерируютсяnode_modules
.components
— это проект для общих компонентов, аapps
— проект для корпоративного приложения, использующего общие компоненты через"@product/components": "link:../components"
. Пакеты вnode_modules
используются какcomponents
, так иapps
. - У нас есть три сборника рассказов в монорепозитории: основной сборник рассказов, компонентный сборник рассказов и сборник рассказов приложения. Корневой сборник рассказов состоит из двух других сборников рассказов.
.storybook
— это папка для конфигурации Storybook.main.js
настраивает расположение файла истории, надстройки, а также настраиваемые конфигурации Webpack и Babel.preview.js
устанавливает глобальные настройки для декораторов, параметров и глобальных типов.style.css
— это один из шести способов определения глобальных стилей.
Задача состоит в том, чтобы обновить Storybook до версии 7. Из-за сложной настройки Storybook наша миграция не такая гладкая, как в предыдущих версиях. Мы поделимся с вами восьмиэтапным опытом миграции, и мы надеемся, что это может помочь вашим приложениям.
Вот краткое изложение шагов:
- Шаг 1: Соответствовать требованиям
- Шаг 2: Выберите скрипт миграции
- Шаг 3: Выполнить скрипт миграции
- Шаг 4: Исправить проблемы с MDX2
- Шаг 5: Перенесите
main.js
иpreview.js
на TypeScript - Шаг 6: Обновите компонент Storybook
- Шаг 7: Обновите приложение Storybook
- Шаг 8: Удалить композицию Storybook
Соответствовать требованиям
Для Storybook 7 требуется Node 16 или выше, и он больше не поддерживает IE11. Целевая версия браузера — chrome >= 100
. Также требуется Webpack 5.
Сборник рассказов 7 не поддерживает истории, в которых используется storiesOf
. Однако эти истории могут продолжать работать, установив features.storyStoreV7: false
в main.js
со снижением производительности.
Сборник рассказов 7 не поддерживает MDX1. Рекомендуется перейти на MDX2, но MDX1 может продолжать работать, установив features.legacyMdx1: true
в main.js
.
Написание историй непосредственно в MDX устарело в Storybook 7. Рекомендуется документировать истории с помощью простого .mdx
и писать настоящие истории в CSF3, улучшенной версии CSF2, которая требует написания историй с объектами.
Выберите сценарий миграции
Скрипт миграции Storybook выполняет две задачи:
- Обновите зависимости Storybook до последней версии.
- Запустите набор автоматических миграций, которые:
- Проверьте общие задачи обновления.
- Объясните необходимые изменения со ссылками на дополнительную информацию.
- Попросите одобрения, а затем выполните задание.
Предоставляется три сценария миграции: automigrate
, upgrade
и prerelease
.
Скрипт автоматической миграции
Вот команда для запуска скрипта автоматической миграции:
$ npx storybook@next automigrate
Он запускает стандартные проверки конфигурации, объясняет, что потенциально устарело, и предлагает исправить это автоматически. Однако он не обновляет пакеты Storybook.
Скрипт обновления
Вот команда для запуска скрипта обновления:
$ npx storybook@latest upgrade
Он обновляет пакеты Storybook до последней стабильной версии, выполняет проверки достоверности версий пакетов и выполняет автоматическую миграцию для проверки конфигурации.
Предрелизный сценарий
Вот команда для запуска сценария предварительной версии:
$ npx storybook@latest upgrade --prerelease
Сборник рассказов находится в постоянном развитии, а предварительные версии публикуются почти ежедневно. Лучше всего опробовать новые функции до того, как они станут общедоступными.
Выполнить сценарий миграции
Сценарий обновления — это наиболее распространенный способ обновления Storybook, и мы используем его для прохождения процесса миграции.
В root
выполните скрипт:
$ npx storybook@latest upgrade
Скрипт выполняется в несколько шагов.
Установите пакеты Storybook 7
Сценарий обновления проверяет наличие последних версий пакетов сборника рассказов и показывает, что необходимо обновить:
info @storybook/addon-actions ^6.5.16 → ^7.0.11 info @storybook/addon-essentials ^6.5.16 → ^7.0.11 info @storybook/addon-links ^6.5.16 → ^7.0.11 info @storybook/addons ^6.5.16 → ^7.0.11 info @storybook/react ^6.5.16 → ^7.0.11 info @storybook/theming ^6.5.16 → ^7.0.11 info eslint-plugin-storybook ^0.6.11 → ^0.6.12 info storybook-dark-mode ^2.1.1 → ^3.0.0
Он находит несколько устаревших пакетов в yarn.lock
и выводит предупреждающие сообщения:
WARN Found 5 outdated packages (relative to '@storybook/[email protected]') WARN Please make sure your packages are updated to ensure a consistent experience. WARN - @storybook/[email protected] WARN - @storybook/[email protected] WARN - @storybook/[email protected] WARN - @storybook/[email protected] WARN - @storybook/[email protected] 🔎 checking possible migrations..
devDpendencies
в package.json
обновлены до следующего:
"devDependencies": { "@storybook/addon-actions": "^7.0.11", "@storybook/addon-essentials": "^7.0.11", "@storybook/addon-links": "^7.0.11", "@storybook/addons": "^7.0.11", "@storybook/core": "^6.5.16", "@storybook/react": "^7.0.11", "@storybook/theming": "^7.0.11", "eslint-plugin-storybook": "^0.6.12", "storybook-dark-mode": "^3.0.0" }
Вы заметили, что @storybook/core
не обновляется? Нам нужно справиться с этим вручную.
Установите двоичный файл сборника рассказов и обновите скрипты
Сборник рассказов 6 содержит двоичные файлы с именами start-storybook
и build-storybook
. В Storybook 7 эти двоичные файлы удалены и заменены новой командой CLI, storybook
. storybook dev
запускает сборник рассказов, а storybook build
создает сборник рассказов.
storybook
ищет поле framework
в main.js
и использует его, чтобы определить, как начать или построить сборник рассказов. Преимущество этого изменения заключается в том, что теперь можно установить несколько фреймворков в проекте, не беспокоясь о проблемах с подъемом.
Сценарий обновления сначала спрашивает, следует ли установить двоичный файл storybook
.
🔎 found a 'storybook-binary' migration: ╭ Automigration detected ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ We've detected you are using Storybook 7.0.11 without Storybook's storybook binary. Starting in Storybook 7.0, it has to be installed. │ │ │ │ │ │ More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#start-storybook--build-storybook-binaries-removed │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✔ Do you want to run the 'storybook-binary' migration on your project? (Y/n)
Введите y
, и он запустит миграцию storybook-binary
.
storybook
добавляется к devDpendencies
в package.json
:
"devDependencies": { "storybook": "^7.0.11" }
Затем сценарий обновления спрашивает, следует ли исправить сборник рассказов scripts
в package.json
.
🔎 found a 'sb-scripts' migration: ╭ Automigration detected ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ We've detected you are using Storybook 7.0.11 with scripts from previous versions of Storybook. │ │ Starting in Storybook 7, the start-storybook and build-storybook binaries have changed to storybook dev and storybook build respectively. │ │ In order to work with Storybook 7.0.11, your storybook scripts have to be adjusted to use the binary. We can adjust them for you: │ │ │ │ build-storybook │ │ from: │ │ build-storybook │ │ to: │ │ storybook build │ │ │ │ storybook │ │ from: │ │ start-storybook -p 6006 │ │ to: │ │ storybook dev -p 6006 │ │ │ │ In case this migration did not cover all of your scripts, or you'd like more info: │ │ https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#start-storybook--build-storybook-binaries-removed │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✔ Do you want to run the 'sb-scripts' migration on your project? (Y/n)
Введите y
, и он запустит миграцию sb-scripts
.
scripts
в package.json
обновлены для использования новой команды CLI.
"scripts": { "build-storybook": "storybook build", "storybook": "storybook dev -p 6006", }
Настройка фреймворков
Сборник рассказов 7 представляет концепцию фреймворков, которая абстрагирует конфигурацию для renderers
(React, Vue и т. д.), builders
(Webpack, Vite и т. д.) и значения по умолчанию, чтобы упростить интеграцию.
В Storybook 7 framework
объединяет renderer
и builder
, за исключением нескольких пакетов, которые не содержат нескольких сборщиков, таких как @storybook/angular
, который поддерживает только Webpack 5.
Вот список фреймворков:
@storybook/angular
(то же, что и сборник рассказов 6)@storybook/ember
(то же, что и сборник рассказов 6)@storybook/html-vite
@storybook/html-webpack5
@storybook/preact-vite
@storybook/preact-webpack5
@storybook/react-vite
@storybook/react-webpack5
@storybook/nextjs
@storybook/server-webpack5
@storybook/svelte-vite
@storybook/svelte-webpack5
@storybook/sveltekit
@storybook/vue-vite
@storybook/vue-webpack5
@storybook/vue3-vite
@storybook/vue3-webpack5
@storybook/web-components-vite
@storybook/web-components-webpack5
Сценарий обновления спрашивает, нужно ли настраивать фреймворки:
🔎 found a 'new-frameworks' migration: ╭ Automigration detected ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ We've detected your project is not fully setup with Storybook's 7 new framework format. │ │ │ │ Storybook 7 introduced the concept of frameworks, which abstracts configuration for renderers (e.g. React, Vue), builders (e.g. Webpack, Vite) and │ │ defaults to make integrations easier. │ │ │ │ Your project should be updated to use Storybook's framework: @storybook/react-webpack5. We can attempt to do this for you automatically. │ │ │ │ Here are the steps this migration will do to migrate your project: │ │ - Add the following dependencies: │ │ - * @storybook/react-webpack5 │ │ - Update or specify the framework field in .storybook/main.js with the value of "@storybook/react-webpack5". │ │ │ │ │ │ To learn more about the new framework format, see: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#new-framework-api │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ? Do you want to run the 'new-frameworks' migration on your project? › (Y/n)
Введите y
, и он запустит миграцию new-frameworks
.
Поскольку это приложение React, @storybook/react-webpack5
добавляется к devDpendencies
в package.json
:
"devDependencies": { "@storybook/react-webpack5": "^7.0.11" }
main.js
был обновлен полем framework
:
module.exports = { ... framework: { name: "@storybook/react-webpack5", options: {} } };
Перенос MDX1 в MDX2
MDX позволяет использовать JSX внутри содержимого уценки. Он может импортировать компоненты, такие как интерактивные диаграммы или оповещения, и вставлять их в файл уценки. Версия 2 многомерных выражений (MDX2) была выпущена 1 февраля 2022 г. с улучшенной производительностью и улучшенным синтаксисом. Он поддерживает любую среду выполнения JSX, включая React, Preact, Vue, Emotion и т. д.
Сборник рассказов 7 использует MDX2 вместо MDX1 для записи .stories.mdx
файлов, определяющих и документирующих истории. Сценарий обновления обнаруживает, что у нас есть 84 файла .stories.mdx
, и спрашивает, следует ли перенести их в MDX2:
🔎 found a 'mdx1to2' migration: ╭ Automigration detected ──────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ We've found 84 '.stories.mdx' files in your project. │ │ │ │ Storybook has upgraded to MDX2 (https://mdxjs.com/blog/v2/), which contains breaking changes from MDX1. │ │ We can try to automatically upgrade your MDX files to MDX2 format using some common patterns. │ │ │ │ After this install completes, and before you start Storybook, we strongly recommend reading the MDX2 section │ │ of the 7.0 migration guide. It contains useful tools for detecting and fixing any remaining issues. │ │ │ │ https://storybook.js.org/migration-guides/7.0 │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ? Do you want to run the 'mdx1to2' migration on your project? › (Y/n)
Введите y
, и он запустит миграцию mdx1to2
.
Собственно, для этих 84 файлов никаких изменений не производилось.
Настроить опцию автодокументации
Написание историй непосредственно в MDX (файлы .stories.mdx
) устарело в Storybook 7. Рекомендуется документировать истории с помощью простых .mdx
и писать истории в CSF3, улучшенной версии CSF2, которая требует написания историй с объектами.
Раньше Docs
была вкладкой рядом с Canvas
, которая отображала каждую историю в режиме просмотра документов.
В Storybook7 autodocs
добавляет дополнительные записи на боковую панель для историй.
autodocs
можно настроить в main.js
, а имя папки можно настроить.
module.exports = { docs: { autodocs: true, defaultName: 'Docs' } };
autodocs
может принимать следующие три значения:
true
: Он автоматически создает документы для каждого файла истории.false
: Он никогда не создает документы.tag
: Документы создаются только для файлов историй с тегомautodocs
. Вот пример:
export default { component: MyComponent, tags: ['autodocs'] }
Сценарий обновления спрашивает, установить ли autodocs
значение true:
🔎 found a 'autodocsTrue' migration: ╭ Automigration detected ────────────────────────────────────────────────────────────────────────────╮ │ │ │ We've changed the configuration of autodocs (previous docsPage), so now the value: │ │ - docs.autodocs: true -- means automatically create docs for every CSF file │ │ - docs.autodocs: 'tag' -- means only create autodocs for CSF files with the 'autodocs' tag │ │ - docs.autodocs: false -- means never create autodocs │ │ │ │ Based on your prior configuration, we can set the `docs.autodocs` to keep your old behaviour: │ │ │ │ docs: { autodocs: true } │ │ │ │ More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#autodocs-changes │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ? Do you want to run the 'autodocsTrue' migration on your project? › (Y/n)
Введите y
, и он запустит миграцию autodocsTrue
.
main.js
был обновлен полем docs
:
module.exports = { ... framework: { name: "@storybook/react-webpack5", options: {} }, docs: { autodocs: true } };
Создайте настройки babel для root
Babel — это цепочка инструментов, которая в основном используется для преобразования кода ECMAScript 2015+ и/или TypeScript в обратно совместимую версию JavaScript в текущих и более старых браузерах или средах. Сборник рассказов 7 теперь использует исключительно режим Babel v7. По умолчанию для babelModeV7
установлено значение true
в main.js
. Поскольку это значение по умолчанию, в настройке нет необходимости.
module.exports = { features: { babelModeV7: true } }
Storybook читает конфигурацию babel проекта, .babelrc.json
, babel.config.js
и т. д.
Сценарий обновления спрашивает, нужно ли создать файл .babelrc.json
с некоторой базовой конфигурацией и добавить в devDependencies
все необходимые пакеты.
🔎 found a 'missing-babelrc' migration: ╭ Automigration detected ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ We detected that your project does not have a babel configuration (.babelrc, babel.config.js, etc.). │ │ │ │ In version 6.x, Storybook provided its own babel settings out of the box. Now, Storybook re-uses your project's babel configuration, with small, │ │ incremental updates from Storybook addons. │ │ │ │ If your project does not have a babel configuration file, we can generate one that's equivalent to the 6.x defaults for you. Keep in mind that this can │ │ affect your project if it uses babel, and you may need to make additional changes based on your projects needs. │ │ │ │ Note: This automatic setup doesn't work in a monorepo, see the babel documentation for how to setup babel manually: │ │ https://babeljs.io/docs │ │ │ │ We can create a .babelrc.json file with some basic configuration and add any necessary package devDependencies. │ │ │ │ Please see the migration guide for more information: │ │ https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#babel-mode-v7-exclusively │ │ │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ? Do you want to run the 'missing-babelrc' migration on your project? › (Y/n)
Введите y
, и он запустит миграцию missing-babelrc
, которая спросит, добавить ли @babel/preset-env
, @babel/preset-typescript
и @babel/preset-react
.
✔ Do you want to add the TypeScript preset? … yes ✔ Do you want to add the React preset? … yes info Writing file to root/.babelrc.json ✔ Shall we install the required dependencies now? (@babel/preset-env, @babel/preset-typescript, @babel/preset-react) … yes
@babel/preset-env
: Это интеллектуальная предустановка для использования новейшего JavaScript без микроуправления синтаксическими преобразованиями.@babel/preset-typescript
: рекомендуемый пресет для TypeScript.@babel/preset-react
: рекомендуемый пресет для React. Начиная с режима Babel v7,@babel/preset-react
не включает@babel/preset-flow
.
Вот сгенерированный .babelrc.json
:
{ "sourceType": "unambiguous", "presets": [ [ "@babel/preset-env", { "targets": { "chrome": 100 } } ], "@babel/preset-typescript", "@babel/preset-react" ], "plugins": [] }
Резюме и продолжение
В конце сценарий обновления выводит сводку:
╭ Migration check ran successfully ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ Successful migrations: │ │ │ │ storybook-binary, sb-scripts, new-frameworks, mdx1to2, autodocsTrue, missing-babelrc │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ If you'd like to run the migrations again, you can do so by running 'npx storybook@next automigrate' │ │ │ │ The automigrations try to migrate common patterns in your project, but might not contain everything needed to migrate to the latest version of │ │ Storybook. │ │ │ │ Please check the changelog and migration guide for manual migrations and more information: https://storybook.js.org/migration-guides/7.0 │ │ And reach out on Discord if you need help: https://discord.gg/storybook │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ Attention: The following dependencies are duplicated which might cause unexpected behavior: │ │ │ │ @storybook/core-server: │ │ 7.0.11, 6.5.16 │ │ │ │ @storybook/core-common: │ │ 7.0.11, 6.5.16 │ │ │ │ @storybook/csf-tools: │ │ 7.0.11, 6.5.16 │ │ │ │ @storybook/node-logger: │ │ 7.0.11, 6.5.16 │ │ │ │ @storybook/telemetry: │ │ 7.0.11, 6.5.16 │ │ │ │ You can find more information for a given dependency by running yarn why <package-name> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Здесь показаны выполненные сценарии: storybook-binary
, sb-scripts
, new-frameworks
, mdx1to2
, autodocsTrue
и missing-babelrc
.
Есть предупреждение о @storybook 6.5.16
пакетах, и нам нужно удалить @storybook/core
из devDpendencies
в package.json
.
"devDependencies": { "@storybook/addon-actions": "^7.0.11", "@storybook/addon-essentials": "^7.0.11", "@storybook/addon-links": "^7.0.11", "@storybook/addons": "^7.0.11", "@̶s̶t̶o̶r̶y̶b̶o̶o̶k̶/c̶o̶r̶e̶":̶ "^̶6̶.5̶.1̶6̶", "@storybook/react": "^7.0.11", "@storybook/theming": "^7.0.11" }
Повторно выполните npx storybook@latest upgrade
и пропустите миграцию mdx1to2
:
╭ Migration check ran successfully ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ Skipped migrations: │ │ │ │ mdx1to2 │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ If you'd like to run the migrations again, you can do so by running 'npx storybook@next automigrate' │ │ │ │ The automigrations try to migrate common patterns in your project, but might not contain everything needed to migrate to the latest version of │ │ Storybook. │ │ │ │ Please check the changelog and migration guide for manual migrations and more information: https://storybook.js.org/migration-guides/7.0 │ │ And reach out on Discord if you need help: https://discord.gg/storybook │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ You can find more information for a given dependency by running yarn why <package-name> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
В сводке больше нет предупреждений.
Устранение проблем с MDX2
Storybook 7 по умолчанию использует MDX2 для рендеринга документов. MDX1 можно использовать со следующей конфигурацией, но это не рекомендуется.
module.exports = { features: { legacyMdx1: true } }
Обновление с MDX1 до MDX2 не полностью автоматизировано из-за большого количества изменений между версиями. Выполните следующую команду для обнаружения ошибок:
$ npx @hipster/mdx2-issue-checker
Вот несколько примеров того, что нужно исправить:
"Actions for {object name}" => "Actions for \{object name\}" The number cannot exceed 7 (<7) => The number cannot exceed 7 (`<7`) const count = 1; => export const count = 1;
Также есть это предупреждение во время миграции.
info => Loading presets WARN The "@storybook/addon-mdx-gfm" addon is meant as a migration assistant for Storybook 7.0; and will likely be removed in a future version. WARN It's recommended you read this document: WARN https://storybook.js.org/docs/react/writing-docs/mdx#lack-of-github-flavored-markdown-gfm WARN WARN Once you've made the necessary changes, you can remove the addon from your package.json and storybook config.
@storybook/addon-mdx-gfm
предназначен в качестве помощника по миграции для Storybook 7.0, обеспечивая поддержку Github Flavored Markdown для документов Storybook. После внесения необходимых изменений этот аддон можно удалить из package.json
и конфигурации сборника рассказов. Удаление должно быть сделано вручную.
Перенесите main.js и preview.js на TypeScript
Storybook 7 поддерживает TypeScript для файлов main
и preview
. Мы вручную переносим их на TypeScripts.
Вот root/.storybook/main.ts
:
import { StorybookConfig } from '@storybook/react-webpack5'; const config: StorybookConfig = { stories: ['./*.story.@(js|jsx|ts|tsx)'], addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-mdx-gfm'], refs: { components: { title: 'components', url: 'https://localhost:6007' }, apps: { title: 'apps', url: 'https://localhost:6008' } }, framework: { name: '@storybook/react-webpack5', options: {fastRefresh: true} }, docs: { autodocs: true } };
Вот root/.storybook/preview.ts
:
import { Preview } from '@storybook/react'; const preview: Preview = { parameters: { actions: {argTypesRegex: '^on[A-Z].*'}, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, } }; export default preview;
На данный момент мы закончили миграцию на root
.
Обновите сборник рассказов о компонентах
С монорепозиторием мы должны вручную внести изменения в сборник рассказов в root/components
.
Для внесения изменений требуется несколько шагов.
Переименуйте и измените main.ts
Переименуйте root/components/.storybook/main.js
в root/components/.storybook/main.ts
. Примите изменения с root/.storybook/main.ts
по root/components/.storybook/main.ts
.
import { StorybookConfig } from '@storybook/react-webpack5'; // find stories const stories = ... const config: StorybookConfig = { stories, addons: [ '@storybook/addon-links', '@storybook/addon-essentials', 'storybook-dark-mode' ], webpackFinal: async (config) => ({ ...config, devtool: 'eval-source-map' }), framework: { name: "@storybook/react-webpack5", options: { fastRefresh: true }, }, docs: { autodocs: true }, features: { storyStoreV7: false } }; export default config;
В приведенной выше конфигурации для storyStoreV7
установлено значение false
, поскольку у нас все еще есть устаревшие истории, в которых используется storiesOf
.
Есть еще предупреждения, но эти истории работают до поры до времени.
In SB7, we use the next-generation `storyStoreV7` by default, which does not support `storiesOf`. More info, with details about how to opt-out here: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#storystorev7-enabled-by-default Unexpected `storiesOf` usage: (line 38, col 0).
Переименуйте и измените файл preview.jsx.
Переименуйте root/components/.storybook/preview.jsx
в root/components/.storybook/preview.tsx
. Примите изменения в root/.storybook/preview.ts
по root/components/.storybook/preview.tsx
:
import * as React from 'react'; import { Preview } from '@storybook/react'; import 'antd/dist/antd.css'; import '@ant-design/compatible/assets/index.css'; import { useDarkMode } from 'storybook-dark-mode'; import ProductThemeProvider from '../src/styled/ProductThemeProvider'; import './style.css'; const preview: Preview = { parameters: { darkMode: { stylePreview: true, classTarget: 'body', darkClass: 'darkClass', lightClass: 'lightClass', }, actions: {argTypesRegex: '^on[A-Z].*'}, controls: { expanded: true, matchers: { color: /(background|color)$/i, date: /Date$/, }, }, options: { storySort: { order: [ // ordered stories ] }, }, } }; export default preview; const withThemeProvider = (Story, context) => { const [someState, useSomeState] = React.useState(); return ( <ProductThemeProvider isDarkMode={useDarkMode()} isStorybook={true} someState={someState}> <Story {...context} useSomeState={useSomeState}/> </ProductThemeProvider> ); }; export const decorators = [withThemeProvider];
Скрипты обновления в root/components/package.json
Обновите scripts
в root/components/package.json
с помощью команды CLI storybook
, чтобы запустить и создать сборник рассказов.
"scripts": { "storybook": "../../node_modules/.bin/storybook dev -p 6007", "build-storybook": "../../node_modules/.bin/storybook build" }
Создайте .babelrc.json и исправьте сборку
Мы обновили main
, preview
и scripts
.
Выполните yarn storybook
, и он не сможет скомпилировать TypeScript:
ModuleBuildError: Module build failed (from ../../node_modules/@storybook/builder-webpack5/node_modules/babel-loader/lib/index.js): SyntaxError: root/components/src/components/ProductComp.tsx: Unexpected token, expected "," (12:25) 10 | } 11 | `; > 12 | const getOptions = (products: Product[]) => { | ^
.babelrc.json
это спасение. Скопируйте root/.babelrc.json
в root/components/.babelrc.json
.
{ "sourceType": "unambiguous", "presets": [ [ "@babel/preset-env", { "targets": { "chrome": 100 } } ], "@babel/preset-typescript", "@babel/preset-react" ], "plugins": [] }
Конфигурация Babel решила проблему компиляции TypeScript, но показывает новую ошибку:
ModuleNotFoundError: Module not found: Error: Can't resolve 'stream' in 'root/node_modules/csv-parse/lib/es5' BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it. If you want to include a polyfill, you need to: - add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }' - install 'stream-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "stream": false }
Предлагает установить stream-browserify
. На самом деле у нас установлено stream-browserify
:
$ yarn why stream-browserify ... => Found "[email protected]" info Reasons this module exists - "webpack#node-libs-browser" depends on it - Hoisted from "webpack#node-libs-browser#stream-browserify"
Давайте добавим stream-browserify
в резервную конфигурацию в main.ts
:
import { StorybookConfig } from '@storybook/react-webpack5'; // find stories const stories = ... const config: StorybookConfig = { stories, addons: [ '@storybook/addon-links', '@storybook/addon-essentials', 'storybook-dark-mode' ], webpackFinal: async (config) => { const fallback = config.resolve.fallback || {}; Object.assign(fallback, { stream: require.resolve("stream-browserify"), }); config.resolve.fallback = fallback; return ({ ...config, devtool: 'eval-source-map' }) }, framework: { name: "@storybook/react-webpack5", options: { fastRefresh: true }, }, docs: { autodocs: true }, features: { storyStoreV7: false } }; export default config;
Кроме того, мы добавляем @types/webpack-env
, определение типа для Webpack, к devDpendencies
в package.json
, чтобы устранить дальнейшие ошибки типов, возникающие из ../../node_modules/@storybook/builder-webpack5/node_modules/babel-loader/lib/index.js
.
"devDependencies": { "@types/webpack-env": "^1.18.0" }
Определите types
в tsconfig.json
, чтобы включить webpack-env
:
"types": ["node", "webpack-env", ...]
Сборка исправлена. Запустится компонент Storybook.
╭──────────────────────────────────────────────────╮ │ │ │ Storybook 7.0.11 for react-webpack5 started │ │ 214 ms for manager and 48 s for preview │ │ │ │ Local: https://localhost:6007/ │ │ On your network: https://169.254.1.1:6007/ │ │ │ ╰──────────────────────────────────────────────────╯
Исправить фавикон и декораторы истории
Перейдите на https://localhost:6007
и просмотрите компонент Storybook:
Есть две проблемы:
- В сборнике рассказов нет фавикона, небольшого значка, связанного с конкретным веб-сайтом или веб-страницей.
- Компонент
Button
не имеет связанных стилей.
Мы создаем значок сборника рассказов по адресу root/public/storybook.ico
и добавляем root/components/.storybook/manager-head.html
, чтобы включить этот значок:
<link rel="shortcut icon" href="/storybook.ico">
Это исправляет фавикон.
Мы использовали декораторы для применения стилей decorators = [withThemeProvider]
. Однако синтаксис декораторов был изменен в Storybook 7. Вместо этого decorators
становится полем root/components/.storybook/preview.tsx
:
const preview: Preview = { ... decorators: [ (Story, context) => { const [someState, useSomeState] = React.useState(); return ( <ProductThemeProvider isDarkMode={useDarkMode()} isStorybook={true} someState={someState}> <Story {...context} useSomeState={useSomeState}/> </ProductThemeProvider> ); } ], };
Это исправляет стиль компонента Button.
В root/components
выполните yarn storybook
, и все работает.
Есть еще одна проблема развития. fetch-mock
, библиотека JavaScript для имитации HTTP-запросов, выдает ошибку во время горячей перезагрузки: fetch-mock: No fallback response defined for GET to /runtime_main.b83bdb3a8714964066e2.hot-update.json
.
Это можно исправить, установив fetchMock.config.fallbackToNetwork = true
, хотя для Storybook 6 этот параметр не нужен.
Поскольку preview.tsx
задает глобальную настройку для декораторов, параметров и глобальных типов, мы добавляем в нее настройку fetchMock
:
import * as React from 'react'; import { Preview } from '@storybook/react'; import 'antd/dist/antd.css'; import '@ant-design/compatible/assets/index.css'; import { useDarkMode } from 'storybook-dark-mode'; import ProductThemeProvider from '../src/styled/ProductThemeProvider'; import './style.css'; import fetchMock from 'fetch-mock'; fetchMock.config.fallbackToNetwork = true; const preview: Preview = { parameters: { darkMode: { stylePreview: true, classTarget: 'body', darkClass: 'darkClass', lightClass: 'lightClass', }, actions: {argTypesRegex: '^on[A-Z].*'}, controls: { expanded: true, matchers: { color: /(background|color)$/i, date: /Date$/, }, }, options: { storySort: { order: [ // ordered stories ] }, }, }, decorators: [ (Story, context) => { const [someState, useSomeState] = React.useState(); return ( <ProductThemeProvider isDarkMode={useDarkMode()} isStorybook={true} someState={someState}> <Story {...context} useSomeState={useSomeState}/> </ProductThemeProvider> ); } ], }; export default preview;
Теперь он хорошо работает и в режиме разработки.
Обновите сборник рассказов о приложении
С монорепозиторием мы должны вручную внести изменения в сборник рассказов в root/apps
.
Аналогично компоненту Storybook мы вносим следующие изменения:
- Переименуйте и измените
main.ts
+ добавьте резервную конфигурацию. - Переименуйте и измените
preview.jsx
+ Исправьте историюdecorators
+ Добавьте параметрfetchMock
. - Обновите скрипты в
root/components/package.json
. - Создайте
.babelrc.json
. - Исправить фавикон.
- Исправление декораторов истории.
Выполните yarn storybook
, и мы не сможем скомпилировать TypeScript. .babelrc.json
необходимо переименовать в babel.config.json
:
{ "sourceType": "unambiguous", "presets": [ [ "@babel/preset-env", { "targets": { "chrome": 100 } } ], "@babel/preset-typescript", "@babel/preset-react" ], "plugins": [] }
В чем разница между .babelrc.json
и babel.config.json
?
.babelrc.json
— это конфигурация, которая применяется только к одной части проекта.babel.config.json
— это конфигурация для монорепозитория, и она компилируетnode_modules
.
Наше приложение размещено в монорепозитории. Поскольку root/components
действует как единый репозиторий, .babelrc.json
все еще работает. Однако root/apps
связывается с общими компонентами через "@product/components": "link:../components
. В нем есть несколько файлов package.json
, и вместо них следует использовать babel.config.json
, хотя содержимое такое же.
В root/apps
выполните yarn storybook
.
╭──────────────────────────────────────────────────╮ │ │ │ Storybook 7.0.11 for react-webpack5 started │ │ 306 ms for manager and 45 s for preview │ │ │ │ Local: https://localhost:6008/ │ │ On your network: https://169.254.1.1:6008/ │ │ │ ╰──────────────────────────────────────────────────╯
Сборник рассказов работает, и вот как он выглядит:
Удалить сборник рассказов о композиции
Состав сборника рассказов позволяет нам просматривать компоненты из любого сборника рассказов, доступного через статический URL-адрес или локальный URL-адрес.
Вот root/.storybook/main.ts
, который мы используем для ссылки на два местных сборника рассказов:
import { StorybookConfig } from '@storybook/react-webpack5'; const config: StorybookConfig = { stories: ['./*.story.@(js|jsx|ts|tsx)'], addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-mdx-gfm'], refs: { components: { title: 'components', url: 'https://localhost:6007' }, apps: { title: 'apps', url: 'https://localhost:6008' } }, framework: { name: '@storybook/react-webpack5', options: {fastRefresh: true} }, docs: { autodocs: true } };
Не работает с обновленным компонентом Storybook и приложением Storybook.
Мы создали составной сборник рассказов, чтобы разместить несколько сборников рассказов на одной панели. Однако для этого требуются все локальные сборники рассказов. Это неудобно и ресурсоемко. Мы решили удалить его, а не исправить.
Заключение
Мы прошли восьмиэтапный процесс миграции, чтобы узнать, как обновить несколько сборников рассказов до версии 7 в монорепозитории. Есть проблемы и решения. Надеемся, наш опыт будет полезен для ваших приложений.
Спасибо за прочтение.
Благодарю Сушмитху Аиту, С. Шрирама, Раджасекхара Гандаварапу, Уриана Чанга и Ричарда Тома за работу со мной над продуктами Domino.
Want to Connect? If you are interested, check out my directory of web development articles.