Problems and Solutions Upgrading to Storybook 7 (2023)

Sharing the eight-step migration experience with multiple Storybooks in a monorepo

Problems and Solutions Upgrading to Storybook 7 (1)

·

Follow

Published in

Better Programming

·

20 min read

·

May 18

--

Problems and Solutions Upgrading to Storybook 7 (3)

Storybook is a tool for UI development. It makes development faster and easier by isolating components. This allows us to work on one component at a time. It streamlines UI development, testing, and documentation.

Storybook 7 was released on April 3, 2023. It is the first major release in over two years and by far the largest ever. It brings a lot of features:

  • First-class Vite support
  • Zero-config support for NextJS and SvelteKit powered by the new frameworks API
  • Component Story Format 3 (CSF3) with improved type safety
  • MDX2 support and streamlined doc blocks
  • UI design refresh
  • Improved interaction testing and test coverage
  • Ecosystem CI for better stability and smoother upgrades

We were at Storybook 6 using React and Webpack, with three Storybooks defined in a monorepo, a software development strategy in which the code for several projects is stored in the same repository.

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
  • The repository has a root, where the global package.json is defined and node_modules are generated. components is a project for common components, and apps is a project for an enterprise application using common components via "@product/components": "link:../components". The packages in node_modules are shared by both components and apps.
  • We have three Storybooks in the monorepo, the root Storybook, the component Storybook, and the app Storybook. The root Storybook is the composition of the other two Storybooks.
  • .storybook is a folder for Storybook configuration. main.js configures story file location, add-ons, as well as custom Webpack and Babel configurations. preview.js sets the global setting for decorators, parameters, and global types. style.css is one of the six ways to define global styles.

The task is to upgrade Storybooks to version 7. With a complicated Storybook setup, our migration is not as smooth as previous versions. We share the eight-step migration experience with you, and hopefully, it might help your applications.

Here is the summary of the steps:

  • Step 1: Meet the requirements
  • Step 2: Choose a migration script
  • Step 3: Execute the migration script
  • Step 4: Fix MDX2 Issues
  • Step 5: Migrate main.js and preview.js to TypeScript
  • Step 6: Upgrade the component Storybook
  • Step 7: Upgrade the app Storybook
  • Step 8: Remove the composition Storybook

Storybook 7 requires Node 16 or above, and it no longer supports IE11. The target browser version is chrome >= 100. It also requires Webpack 5.

Storybook 7 does not support stories that use storiesOf. However, these stories can continue to work by setting features.storyStoreV7: false in main.js, with the performance penalty.

Storybook 7 does not support MDX1. It is recommended to migrate to MDX2, but MDX1 can continue to work by setting features.legacyMdx1: true in main.js.

Writing stories directly in MDX has been deprecated in Storybook 7. It is recommended to document stories with simple .mdx, and write actual stories in CSF3, an improved version of CSF2 that requires writing stories with objects.

A Storybook migration script accomplishes two tasks:

  1. Upgrade Storybook dependencies to the latest version.
  2. Run a collection of automigrations, which will:
  • Check for common upgrade tasks.
  • Explain the necessary changes with links to more information.
  • Ask for approval, and then perform the task.

There are three migration scripts provided, automigrate, upgrade, and prerelease.

Automigrate Script

Here is the command to run automigrate script:

$ npx storybook@next automigrate

It runs standard configuration checks, explains what is potentially out-of-date, and offers to fix it automatically. However, it does not upgrade Storybook packages.

Upgrade script

Here is the command to run the upgrade script:

$ npx storybook@latest upgrade

It upgrades the Storybook packages to the latest stable version, performs confidence checks of package versions, and executes automigrate to check the configuration.

Prerelease script

Here is the command to run the prerelease script:

$ npx storybook@latest upgrade --prerelease

Storybook is under constant development, and prerelease versions are published almost daily. It is best to try out new features before they are generally available.

The upgrade script is the most common way to upgrade Storybook, and we use it to walk through the migration process.

At root, execute the script:

$ npx storybook@latest upgrade

The script runs in a few steps.

Install Storybook 7 packages

The upgrade script checks for the latest versions of storybook packages and displays what needs to be upgraded:

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

It finds several outdated packages in yarn.lock, and prints out the warning messages:

WARN Found 5 outdated packages (relative to '@storybook/addon-actions@7.0.11')
WARN Please make sure your packages are updated to ensure a consistent experience.
WARN - @storybook/core-common@6.5.16
WARN - @storybook/core-events@6.5.16
WARN - @storybook/core@6.5.16
WARN - @storybook/node-logger@6.5.16
WARN - @storybook/telemetry@6.5.16
🔎 checking possible migrations..

The devDpendencies in package.json are upgraded to the following:

"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"
}

Have you noticed that @storybook/core is not upgraded? We need to handle it manually.

Install storybook binary and upgrade scripts

Storybook 6 has binaries called start-storybook and build-storybook. In Storybook 7, these binaries are removed and replaced by a new CLI command, storybook. storybook dev starts a Storybook and storybook build builds a Storybook.

storybook looks for the framework field in main.js, and use it to determine how to start or build a Storybook. The benefit of this change is that it is now possible to install multiple frameworks in a project without worrying about hoisting issues.

The upgrade script first asks whether to install the storybook binary.

🔎 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)

Type y, and it runs the storybook-binary migration.

storybook is added to devDpendencies in package.json:

"devDependencies": {
"storybook": "^7.0.11"
}

Then, the upgrade script asks whether to fix Storybook scripts in 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)

Type y, and it runs the sb-scripts migration.

scripts in package.json are updated to use the new CLI command.

"scripts": {
"build-storybook": "storybook build",
"storybook": "storybook dev -p 6006",
}

Configure frameworks

Storybook 7 introduces the concept of frameworks, which abstracts configuration for renderers (React, Vue, etc.), builders (Webpack, Vite, etc.), and defaults to make integrations easier.

In Storybook 7, framework combines a renderer and a builder, with the exception of a few packages that do not contain multiple builders, such as @storybook/angular, which only has Webpack 5 support.

Here is the list of frameworks:

  • @storybook/angular (same as Storybook 6)
  • @storybook/ember (same as Storybook 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

The upgrade script asks whether to set up frameworks:

🔎 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)

Type y, and it runs the new-frameworks migration.

Since this is a React application, @storybook/react-webpack5 is added to devDpendencies in package.json:

"devDependencies": {
"@storybook/react-webpack5": "^7.0.11"
}

main.js has been updated with the framework field:

module.exports = {
...
framework: {
name: "@storybook/react-webpack5",
options: {}
}
};

Migrate MDX1 to MDX2

MDX allows using JSX inside markdown content. It can import components, such as interactive charts or alerts, and embed them within a markdown file. Version 2 of MDX (MDX2) was released on February 1, 2022, with better performance and improved syntax. It supports any JSX runtime, including React, Preact, Vue, Emotion, etc.

Storybook 7 uses MDX2 instead of MDX1 to write .stories.mdx files that define and document stories. The upgrade script detects that we have 84 .stories.mdx files, and asks whether to migrate them to 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)

Type y, and it runs the mdx1to2 migration.

Actually, for these 84 files, no changes have been made.

Configure autodocs option

Writing stories directly in MDX (.stories.mdx files) has been deprecated in Storybook 7. It is recommended to document stories with simple .mdx, and write stories in CSF3, an improved version of CSF2, that requires writing stories with objects.

Previously, Docs is a tab next to Canvas, which renders each story in docs view mode.

Problems and Solutions Upgrading to Storybook 7 (4)

In Storybook7, autodocs adds additional sidebar entries for stories.

Problems and Solutions Upgrading to Storybook 7 (5)

autodocs can be configured in main.js, and the folder name is configurable.

module.exports = {
docs: {
autodocs: true,
defaultName: 'Docs'
}
};

autodocs can take the following three values:

  • true: It automatically creates docs for every story file.
  • false: It never creates docs.
  • tag: It only creates docs for story files with the autodocs tag. Here is an example:
export default {
component: MyComponent,
tags: ['autodocs']
}

The upgrade script asks whether to set autodocs to 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)

Type y, and it runs the autodocsTrue migration.

main.js has been updated with the docs field:

module.exports = {
...
framework: {
name: "@storybook/react-webpack5",
options: {}
},
docs: {
autodocs: true
}
};

Create root’s babel settings

Babel is a toolchain that is mainly used to convert ECMAScript 2015+ and/or TypeScript code into a backward-compatible version of JavaScript in current and older browsers or environments. Storybook 7 now uses Babel mode v7 exclusively. By default, babelModeV7 is set to true in main.js. Because it is the default value, the setting is not necessary.

module.exports = {
features: {
babelModeV7: true
}
}

Storybook reads the project’s babel configuration, .babelrc.json, babel.config.js, etc.

The upgrade script asks whether to create a .babelrc.json file with some basic configuration and add any necessary packages to 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)

Type y, and it runs the missing-babelrc migration that asks whether to add @babel/preset-env, @babel/preset-typescript, and @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: It is a smart preset to use the latest JavaScript without micromanaging syntax transforms.
  • @babel/preset-typescript: It is a recommended preset for TypeScript.
  • @babel/preset-react: It is a recommended preset for React. Starting from Babel mode v7, @babel/preset-react does not include @babel/preset-flow.

Here is the generated .babelrc.json:

{
"sourceType": "unambiguous",
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": 100
}
}
],
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins": []
}

Summary and followup

At the end, the upgrade script prints out a summary:


╭ 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> │
│ │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

This shows the scripts executed: storybook-binary, sb-scripts, new-frameworks, mdx1to2, autodocsTrue, and missing-babelrc.

There is a warning about @storybook 6.5.16 packages, and we need to remove @storybook/core from devDpendencies in 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"
}

Re-execute npx storybook@latest upgrade, and skip the mdx1to2 migration:

╭ 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> │
│ │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

The summary shows no more warnings.

Storybook 7 uses MDX2 by default for rendering Docs. MDX1 can be used with the following configuration, but it is not recommended.

module.exports = {
features: {
legacyMdx1: true
}
}

The upgrade from MDX1 to MDX2 is not fully automated due to many changes between versions. Execute the following command to detect errors:

$ npx @hipster/mdx2-issue-checker

Here are some examples of what to fix:

"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;

There is also this warning during migration.

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 is meant as a migration assistant for Storybook 7.0, providing Github Flavored Markdown support to Storybook docs. Once the necessary changes are made, this addon can be removed from package.json and storybook configuration. The removal needs to be done manually.

Storybook 7 supports TypeScript for main and preview files. We manually migrate them to TypeScripts.

Here is 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: 'http://localhost:6007'
},
apps: {
title: 'apps',
url: 'http://localhost:6008'
}
},
framework: {
name: '@storybook/react-webpack5',
options: {fastRefresh: true}
},
docs: {
autodocs: true
}
};

Here is 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;

At this point, we have finished the migration at root.

With the monorepo, we have to make manual changes to the Storybook in root/components.

It takes a few steps to make the changes.

Rename and modify main.ts

Rename root/components/.storybook/main.js to root/components/.storybook/main.ts. Adopt the changes in root/.storybook/main.ts to 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;

In the configuration above, storyStoreV7 is set to false, as we still have legacy stories that use storiesOf.

There are still warnings, but these stories work for the time being.

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).

Rename and modify preview.jsx

Rename root/components/.storybook/preview.jsx to root/components/.storybook/preview.tsx. Adopt the changes in root/.storybook/preview.ts to 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];

Upgrade scripts in root/components/package.json

Update scripts in root/components/package.json with the CLI command, storybook, to start and build a Storybook.

"scripts": {
"storybook": "../../node_modules/.bin/storybook dev -p 6007",
"build-storybook": "../../node_modules/.bin/storybook build"
}

Create .babelrc.json and fix the build

We have upgraded main, preview, and scripts.

Execute yarn storybook, and it is not able to compile 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 is the rescue. Copy root/.babelrc.json to root/components/.babelrc.json.

{
"sourceType": "unambiguous",
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": 100
}
}
],
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins": []
}

The Babel configuration has resolved the TypeScript compilation issue, but it shows a new error:

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 }

It suggests installing stream-browserify. In fact, we have stream-browserify installed:

$ yarn why stream-browserify
...
=> Found "stream-browserify@3.0.0"
info Reasons this module exists
- "webpack#node-libs-browser" depends on it
- Hoisted from "webpack#node-libs-browser#stream-browserify"

Let’s add stream-browserify into the fallback configuration in 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;

In addition, we add @types/webpack-env, the type definition for Webpack, to devDpendencies in package.json to resolve further type errors that come from ../../node_modules/@storybook/builder-webpack5/node_modules/babel-loader/lib/index.js.

"devDependencies": {
"@types/webpack-env": "^1.18.0"
}

Define types in tsconfig.json to include webpack-env:

"types": ["node", "webpack-env", ...]

The build is fixed. The component Storybook starts.

╭──────────────────────────────────────────────────╮
│ │
│ Storybook 7.0.11 for react-webpack5 started │
│ 214 ms for manager and 48 s for preview │
│ │
│ Local: http://localhost:6007/ │
│ On your network: http://169.254.1.1:6007/ │
│ │
╰──────────────────────────────────────────────────╯

Fix favicon and story decorators

Go to http://localhost:6007, and view the component Storybook:

Problems and Solutions Upgrading to Storybook 7 (6)

There are two issues:

  • The Storybook does not have a favicon, a small icon associated with a particular website or web page.
  • The Button component does not have associated styles.

We create the Storybook favicon at root/public/storybook.ico, and add root/components/.storybook/manager-head.html to include this icon:

<link rel="shortcut icon" href="/storybook.ico">

This fixes the favicon.

We have used decorators to apply styles by decorators = [withThemeProvider]. However, the decorators syntax has been changed in Storybook 7. Instead, decorators becomes a field of 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>
);
}
],
};

This fixes the Button component styling.

At root/components, execute yarn storybook, and it works well.

Problems and Solutions Upgrading to Storybook 7 (7)

There is another issue for development. fetch-mock, a JavaScript library to mock HTTP requests, throws an error during hot reload: fetch-mock: No fallback response defined for GET to /runtime_main.b83bdb3a8714964066e2.hot-update.json.

Problems and Solutions Upgrading to Storybook 7 (8)

This can be fixed by setting fetchMock.config.fallbackToNetwork = true, although the setting was not needed for Storybook 6.

Because preview.tsx sets the global setting for decorators, parameters, and global types, we add the fetchMock setting in it:

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;

Now, it works well for dev mode as well.

With the monorepo, we have to make manual changes to the Storybook in root/apps.

Similar to the component Storybook, we apply the following changes:

  • Rename and modify main.ts + Add the fallback configuration.
  • Rename and modify preview.jsx + Fix Story decorators + Add the fetchMock setting.
  • Upgrade scripts in root/components/package.json.
  • Create .babelrc.json.
  • Fix favicon.
  • Fix story decorators.

Execute yarn storybook, and we are not able to compile TypeScript. .babelrc.json needs to be renamed to babel.config.json:

{
"sourceType": "unambiguous",
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": 100
}
}
],
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins": []
}

What are the differences between .babelrc.json and babel.config.json?

  • .babelrc.json is a configuration that only applies to a single part of the project.
  • babel.config.json is a configuration for monorepo and it compiles node_modules.

Our application is hosted by a monorepo. Since root/components acts like a single repository, .babelrc.json is still working. However, root/apps links to common components via "@product/components": "link:../components. It has multiple package.json files, and babel.config.json should be used instead, although the content is the same.

At root/apps, execute yarn storybook.

╭──────────────────────────────────────────────────╮
│ │
│ Storybook 7.0.11 for react-webpack5 started │
│ 306 ms for manager and 45 s for preview │
│ │
│ Local: http://localhost:6008/ │
│ On your network: http://169.254.1.1:6008/ │
│ │
╰──────────────────────────────────────────────────╯

The Storybook works, and here’s what it looks like:

Problems and Solutions Upgrading to Storybook 7 (9)

Storybook composition allows us to browse components from any Storybook accessible via static URL or local URL.

Problems and Solutions Upgrading to Storybook 7 (10)

Here is root/.storybook/main.ts that we use to reference two local Storybooks:

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: 'http://localhost:6007'
},
apps: {
title: 'apps',
url: 'http://localhost:6008'
}
},
framework: {
name: '@storybook/react-webpack5',
options: {fastRefresh: true}
},
docs: {
autodocs: true
}
};

It does not work with the upgraded component Storybook and app Storybook.

We have built the composited Storybook to put multiple Storybooks into a single pane. However, it requires all local Storybooks to run. It is inconvenient and resource intensive. We have decided to remove it instead of fixing it.

We have walked through the eight-step migration process on how to upgrade multiple Storybooks to version 7 in a monorepo. There are problems and solutions. Hopefully, our experience is helpful to your applications.

Thanks for reading.

Thanks, Sushmitha Aitha, S Sreeram, Rajasekhar Gandavarapu, Urian Chang, and Richard Tom for working with me on the Domino products.

Want to Connect?

If you are interested, check out my directory of web development articles.

FAQs

What is the minimum node version for Storybook 7? ›

Storybook 7.0 requires Node 16 or above. If you are using an older version of Node, you will need to upgrade or keep using Storybook 6 in the meantime.

What are the framework options for Storybook 7? ›

Storybook 7 introduces zero-config Vite, NextJS, and SvelteKit support. Our new Framework API configures Storybook based on your app settings, including your choice of builder (Webpack & Vite), renderer (React, Vue, Angular, Svelte, HTML), and more!

What are the new features of storybook v7? ›

What's new in Storybook 7.0 Docs?
  • 🏛️ New component-centric information architecture.
  • ⬆️ Upgraded to support MDX2.
  • 🧱 More powerful and consistent Doc Blocks API.
Feb 23, 2023

How do you add controls to a storybook? ›

To use the Controls addon, you need to write your stories using args. Storybook will automatically generate UI controls based on your args and what it can infer about your component. Still, you can configure the controls further using argTypes, see below.

Which node version is recommended? ›

Most users are advised to use the LTS version. New versions of NodeJS involve enhanced performance, the latest features, and bug fixes. The versions of NodeJS are represented with x, y, and z, where x is used to depict the significant or major changes and others are used to depict the minor changes.

Is it mandatory to have NodeJS for Playwright? ›

Playwright requires Node. js version 12 or above. Run node -v from the command line to make sure you have a compatible version of Node. js.

What is the latest version of storybook? ›

Storybook 7.0 - March 2023

SB7. 0 is a full rework of Storybook's core with fast build and next-generation interaction testing. ⚡️ First-class Vite support: Storybook is configured automatically based on your Vite settings, and reduced installation size & startup time.

What is the difference between bit components and storybook? ›

Storybook allows developers to work on components in isolation, while Bit allows developers to version, share, and collaborate on components. Storybook allows developers to customize the development environment, while Bit allows developers to automate the process of building, testing, and deploying components.

What is the equivalent of storybook for Vue? ›

With the release of Vue 3, a Storybook alternative named Histoire has gained some traction.

Is it worth it to use storybook? ›

Storybook has several important use cases for developing high-quality user interfaces and building better, more scalable web applications. Here are a few: UI component development and testing: Storybook allows developers to develop and test UI components in isolation from the application's business logic and data flow.

What are the best storybook alternatives? ›

The best alternatives to Storybooks.io are Kadira, WakaTime, and CodeFactor. If these 3 options don't work for you, we've listed a few more alternatives below.

What libraries are similar to storybook? ›

Top Alternatives to React Storybook
  • Storybook. It is an open source tool for developing UI components in isolation for React, ...
  • React Sketch.app. Managing the assets of design systems in Sketch is complex, error-prone and. ...
  • PrimeNg. ...
  • Laravel Nova. ...
  • LINQPad. ...
  • Laravel Voyager. ...
  • Reactotron. ...
  • Structor.

What is the radio button in storybook? ›

Radio buttons are used when a list of two or more options are mutually exclusive, meaning the user must select only one option.

What is the button component in storybook? ›

Button is a clickable interactive element that triggers a response. You can place text and icons inside of a button. Buttons are often used for form submissions and to toggle elements into view.

How do I manually install storybook? ›

If you want to set up Storybook manually for your Vue project, this is the guide for you.
  1. Step 1: Add dependencies. Add @storybook/vue. ...
  2. Step 2: Add an npm script. ...
  3. Step 3: Create the config file. ...
  4. Step 4: Write your stories.

What is the latest version of Node JS compatible with Windows 7? ›

Nodejs v14 can be used on Win7 but probably last version is v14.

What node versions does Playwright support? ›

System requirements

Playwright requires Node. js version 10.17 or above. The browser binaries for Chromium, Firefox and WebKit work across the 3 platforms (Windows, macOS, Linux):

What version of react does storybook support? ›

Storybook 6.5 supports React 18 and Angular 14 out of the box. When you run your React project for the first time, it will auto-detect the React version and use the new root API if it detects it on React 18.

What version of node does angular 13 require? ›

Note: This introduction uses Angular 13, which requires Node. js version 14.15. 0 or higher.

References

Top Articles
Latest Posts
Article information

Author: Carmelo Roob

Last Updated: 09/27/2023

Views: 6138

Rating: 4.4 / 5 (65 voted)

Reviews: 80% of readers found this page helpful

Author information

Name: Carmelo Roob

Birthday: 1995-01-09

Address: Apt. 915 481 Sipes Cliff, New Gonzalobury, CO 80176

Phone: +6773780339780

Job: Sales Executive

Hobby: Gaming, Jogging, Rugby, Video gaming, Handball, Ice skating, Web surfing

Introduction: My name is Carmelo Roob, I am a modern, handsome, delightful, comfortable, attractive, vast, good person who loves writing and wants to share my knowledge and understanding with you.