Совместное использование восьмиэтапной миграции с несколькими сборниками рассказов в монорепозитории
Введение
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.