Совместное использование восьмиэтапной миграции с несколькими сборниками рассказов в монорепозитории

Введение

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 наша миграция не такая гладкая, как в предыдущих версиях. Мы поделимся с вами восьмиэтапным опытом миграции, и мы надеемся, что это может помочь вашим приложениям.

Вот краткое изложение шагов:

Соответствовать требованиям

Для 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 выполняет две задачи:

  1. Обновите зависимости Storybook до последней версии.
  2. Запустите набор автоматических миграций, которые:
  • Проверьте общие задачи обновления.
  • Объясните необходимые изменения со ссылками на дополнительную информацию.
  • Попросите одобрения, а затем выполните задание.

Предоставляется три сценария миграции: 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.