How to Improve Storybook Performance in Large Projects

November 30, 2024

How to Improve Storybook Performance in Large Projects

In the world of Front-End development, Storybook performance is crucial for building and showcasing components efficiently. However, it has fully evolved beyond into a robust development environment. We all like our dev environment efficient and performant 🙂

When we decided to upgrade our project's Storybook from v7 to v8, we were excited about the new features and improvements. However, we quickly realized that the default configurations were not optimized for our large codebase. Build times were longer, and the development experience wasn't as smooth as we wanted. Storybook v7 in some cases even outperformed v8 (and a GitHub issue is already opened here).

Let's explore how to make your Storybook performance excel even in really large codebases.

1. Use SWC Compiler for Better Storybook Performance

Webpack is powerful but can be slow, especially in large projects. SWC is a quite fast TypeScript/JavaScript compiler written in Rust. By switching to SWC, we significantly reduced our Storybook build times. Storybook supports it out of the box.

First, install the SWC builder and the Webpack 5 manager (since SWC works with Webpack under the hood):

npx storybook@latest add @storybook/addon-webpack5-compiler-swc

In your .storybook/main.js file, specify the builder:

// .storybook/main.js
module.exports = {
  addons: ['@storybook/addon-webpack5-compiler-swc'],
  // swc config for React apps
  swc: config => ({
    ...config,
    jsc: {
      transform: {
        react: {
          runtime: 'automatic',
        },
      },
    },
  }),
  // ...other configurations
}

2. Make Development Mode Where Skip Addons and Docs for Improved Storybook Performance

Addons and documentation generation can slow down Storybook's startup and reload times. During development, you might not need all the addons or docs, so disabling them can speed things up.

Use environment variables to configure Dev Mode. Modify your npm scripts to set a NODE_ENV variable:

// package.json
{
  "scripts": {
    "storybook": "NODE_ENV=production storybook",
    "storybook:dev": "NODE_ENV=development storybook"
  }
}

In your .storybook/main.js, conditionally include addons and disable docs:

// .storybook/main.js
const isDevelopment = process.env.NODE_ENV === 'development';

module.exports = {
  // remove all addons
  addons: isDevelopment
    ? ['@storybook/addon-webpack5-compiler-swc']
    : [
      '@storybook/addon-webpack5-compiler-swc',
      '@storybook/addon-essentials',
      // ...other addons
    ],
  // disable docs generation
  typescript: {
    reactDocgen: false,
  },
}

3. Enable lazyCompilation and File System Cache for Better Storybook Performance

lazyCompilation is a Webpack feature that compiles code on demand rather than upfront. This can drastically reduce initial build times, especially for large codebases. fsCache caches the generated webpack modules and chunks to improve build speed.

In your .storybook/main.js:

// .storybook/main.js
module.exports = {
  core: {
    builder: {
      name: '@storybook/builder-webpack5',
      options: {
        fsCache: true,
        lazyCompilation: true,
      },
    },
  },
  // ...other configurations
}

4. Use Vite as a Builder for Better Storybook Performance

Vite is a fast and modern alternative to Webpack. It's a good choice for building large codebases, so if you can afford it, consider using Vite as a builder for Storybook.

To do that you need to install the necessary packages:

npx storybook@latest add @storybook/builder-vite vite @vitejs/plugin-react

update your .storybook/main.js and configure vite config:

// .storybook/main.js
module.exports = {
  framework: {
    name: '@storybook/react-vite',
    options: {},
  },
  core: {
    builder: {
      name: '@storybook/builder-vite',
      options: {},
    },
  },
  viteFinal: async (config, { configType }) => {
    // modify the Vite config
  },
  // ...other configurations
}

5. Make a Possibility to Load Specific Stories Only for Improved Storybook Performance

When working on a particular component, loading only its stories can save time and resources. This focused approach speeds up Storybook's startup and reload times.

Update your scripts to accept a STORY_PATH environment variable:

// package.json
{
  "scripts": {
    "storybook": "storybook",
    "storybook:dev": "NODE_ENV=development STORY_PATH=src/components/Button/**/*.stories.@(js|jsx|ts|tsx) storybook"
  }
}

In your .storybook/main.js, configure the stories field:

// .storybook/main.js
const path = require('path');

module.exports = {
  stories: [
    process.env.STORY_PATH || 'src/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  // ...other configurations
}

Now, you can start Storybook and specify the stories you want to load:

STORY_PATH=src/components/Button/Button.stories.tsx npm run storybook:dev

Alternatively, you can create a script to pass the story path dynamically.

Final Words

Upgrading to Storybook v8 brought many improvements, but optimizing it for a large project required some tweaks. By switching to the SWC builder, creating a streamlined development mode, enabling lazyCompilation, and loading specific stories, we significantly improved our Storybook performance. These changes not only reduced build and reload times but also enhanced our overall development experience. We hope these tips help you get the most out of Storybook in your large projects. Happy coding!

storybookperformancefrontendfront-endoptimization