storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
83.99k stars 9.23k forks source link

Docs slowing down reloading #12585

Open Sun-2 opened 3 years ago

Sun-2 commented 3 years ago

Reloading changes made to a component is super slow. The build process hangs on 70% - sealing React Docgen Typescript Plugin for 2-3 seconds. Then, tons of react-syntax-highlighter entries are output in the list of built files.

I'm using react-boilerplate-cra-template with storybook added via npx sb init.

I'm not using the docs addon at all.

I've changed main.js to:

const resolve = require('path').resolve;
module.exports = {
  stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/preset-create-react-app',
    {
      name: '@storybook/addon-essentials',
      options: {
        docs: false,
      },
    },
  ]
};

The react-syntax-highlighter files no longer pop up in the list of built files, but the process is still quite slow and it hangs on 70% - sealing React Docgen Typescript Plugin

Environment Info:

  System:
    OS: Linux 5.4 Ubuntu 20.04.1 LTS (Focal Fossa)
    CPU: (24) x64 AMD Ryzen 9 3900X 12-Core Processor
  Binaries:
    Node: 12.18.3 - ~/.nvm/versions/node/v12.18.3/bin/node
    Yarn: 1.22.5 - /usr/bin/yarn
    npm: 6.14.6 - ~/.nvm/versions/node/v12.18.3/bin/npm
  Browsers:
    Chrome: 85.0.4183.102
    Firefox: 80.0.1
  npmPackages:
    @storybook/addon-actions: ^6.0.21 => 6.0.21 
    @storybook/addon-essentials: ^6.0.21 => 6.0.21 
    @storybook/addon-links: ^6.0.21 => 6.0.21 
    @storybook/node-logger: ^6.0.21 => 6.0.21 
    @storybook/preset-create-react-app: ^3.1.4 => 3.1.4 
    @storybook/react: ^6.0.21 => 6.0.21 
shilman commented 3 years ago

@Sun-2 What's the value of stories in main.js?

latviancoder commented 3 years ago

We are experiencing the same after adding docs addon (6.1.0-alpha.17). Previously reload was 1-3 seconds, now it's 10-15.

main.js

  stories: ['../src/**/*.story.@(js|ts|jsx|tsx)'],
  addons: [
    '@storybook/addon-knobs',
    '@storybook/addon-backgrounds',
    '@storybook/addon-actions',
    '@storybook/addon-docs',
  ],
};

We have around 160 story files.

shilman commented 3 years ago

@latviancoder what happens when you configure the following setting in .storybook/main.js:

module.exports = {
  typescript: { reactDocgen: 'react-docgen' }
}
latviancoder commented 3 years ago

Back to 3 seconds, but the prop tables aren't displayed anymore.

shilman commented 3 years ago

@latviancoder so in 5.3 it was 3 seconds AND the prop tables were displaying correctly? cc @hipstersmoothie

latviancoder commented 3 years ago

Just to clarify, we weren't using Docs or any similar addons before 5.3 -> 6 version upgrade.

Nautman commented 3 years ago

@latviancoder what happens when you configure the following setting in .storybook/main.js:

module.exports = {
  typescript: { reactDocgen: 'react-docgen' }
}

This helped me too, thanks!

shilman commented 3 years ago

@sun-2 @latviancoder is it still slowing down reloading in 6.1? i fixed a memory leak and perhaps that solved the problem

RaynalHugo commented 3 years ago

Hello!

I had a similar issue. Rebuilding was taking more than 20 seconds and most of the time seemed to be spent on the docgen plugin.

I tried to migrate to 6.1 but it didn't change anything.

However, I tried your following advice:

@shilman:

@latviancoder what happens when you configure the following setting in .storybook/main.js:

module.exports = {
  typescript: { reactDocgen: 'react-docgen' }
}

And it worked like a charm 👏 🎉 Thank you! Now our rebuild time is around 1 second.

shilman commented 3 years ago

@RaynalHugo Can you do me a favor and see if there are any ts/tsx files in any of your node_modules folders? I really don't know why react-docgen-typescript is so slow in some cases..

RaynalHugo commented 3 years ago

I'd be really happy to help. However, I don't think I can answer your question as you expect.

I am working on a monorepo where we use yarn v2 (berry) with PNP. So, I don't have a standard node_modules folder.

I still have a node_modules folder containing the unplugged packages. Here is what it contains:

/node_modules
  /.cache
    /storybook
      /babel
        - a lot of files like `207f68...f1b541a6fc.json.gz` 
      /dev-server
        - 2 files json files where the names are something like `325c8f4567...8dfad211dc1` (without the .json extension)
        - records.json
    /terser-wepback-plugin
      - contains jsons with uuid names (without the .json extension) nested in folders

I am not sure this helped. I can answer more questions if needed.

Also, note that I am currently back to version 6.0.26, I can migrate to 6.1 if needed.

Nautman commented 3 years ago

I would also like to help but am not sure how. While searching for .tsx files in the node_modules folder I found that storybook-dark-mode uses some. @shilman

I haven't searched for .ts files since there are plenty of them in the node_modules folder, so I don't think there's any point in pointing out those.

shilman commented 3 years ago

@Nautman if i released this on 6.2-alpha would you be able to test it for me? https://github.com/storybookjs/storybook/pull/13053

Nautman commented 3 years ago

Yes! Before you do that I should however let you know that these are my current devDependencies for storybook:

{
    "@storybook/addon-actions": "^6.0.28",
    "@storybook/addon-links": "^6.0.28",
    "@storybook/addons": "^6.0.28",
    "@storybook/preset-create-react-app": "^3.1.5",
    "@storybook/react": "^6.0.28",
    "@types/storybook-react-router": "^1.0.1",
    "storybook-addon-i18next": "^1.3.0",
    "storybook-dark-mode": "^1.0.3",
    "storybook-react-router": "^1.0.8",
}

Would you like me to update and test something before you release it?

shilman commented 3 years ago

@Nautman can you upgrade to 6.1 now and let me know your before and after build times?

hipstersmoothie commented 3 years ago

If anyone could provide an example repo that would be sweet! The typescript plugin comes with some debugging flags so you can see what file it is loading and parsing

https://github.com/hipstersmoothie/react-docgen-typescript-plugin/#debugging

hipstersmoothie commented 3 years ago

For reference we have a design system with 70+ components 700+ stories and the rebuild time spent in the docgen in only a few seconds

Nautman commented 3 years ago

I stripped down my repository digitalungdom.se, branch: rewrite to this example repository

https://github.com/Nautman/storybook-slow-reload-example

It's not as small as it could be, but it has the reproducible issue. If you set

typescript: { reactDocgen: 'react-docgen' }

in main.js you will see the loading times drop and most noticeably it won't get stuck on 70%.

If the example repository is too large, please let me know and perhaps I can strip it a bit further.

EDIT: When trying to strip, I think the issue might have something to do with folders within each other. For example, there was no noticeably difference when editing src/App.tsx. I hope that the repository can be of help, and please let me know if you need any further help!

hipstersmoothie commented 3 years ago

The main reason that react-docgen vs react-docgen-typescript is slower is how each library get the type information.

I've done some optimizations to make react-docgen-typescript quicker:

  1. Made it a plugin that runs once at the end of a build
  2. reuse the typescript "program" to generate docs for each file

These optimization resulted in react-docgen-typescript being much quicker in storybook project. To further optimize the only thing I can think of is a cache stored in tmp that stores docgen information between storybook startups. So if no files changes storybook should start quicker than the last time. I'll look into shuffling some code around in the plugin to see if we can gain any speed there.


If anyone has other ideas on how to optimize the behavior of react-docgen-typescript-plugin I like to merge pull requests ;P

stale[bot] commented 3 years ago

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

amcsi commented 3 years ago

I'm currently up to date using Storybook 6.1.17, and it takes 2-2.5 seconds to reload each time I save a change with start-storybook running.

I'm using TypeScript, and have this in my module.exports for main.js:

    typescript: {
        check: false,
        reactDocgen: false,
    },

If I set reactDocgen to 'react-docgen-typescript', then it's even slower (5-6s) to reload.

This is all really slow. I do not know what to do. Having to wait over 2 seconds to see a light component reloaded does not make for a rapid developer experience.

Am I missing something?

JesusTheHun commented 3 years ago

I've tried both :

typescript: { reactDocgen: 'react-docgen' }

and

typescript: {
    check: false,
    reactDocgen: false,
},

And it still takes more than 10sec. This makes storybooks eats as much time as it makes me save.

JesusTheHun commented 3 years ago

These optimization resulted in react-docgen-typescript being much quicker in storybook project. To further optimize the only thing I can think of is a cache stored in tmp that stores docgen information between storybook startups. So if no files changes storybook should start quicker than the last time. I'll look into shuffling some code around in the plugin to see if we can gain any speed there.

That was exactly my idea. What do you need to get started on this ?

shilman commented 3 years ago

For those of you experiencing slow reload times even with docgen disabled, is it possible that your .storybook/main.js stories glob includes your node_modules directory? That would slow things down a lot..

JesusTheHun commented 3 years ago

Only the project sources are included.

module.exports = {
  stories: [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  (...)
};

I see no difference in performance when switching reactDocgen on/off.

JesusTheHun commented 3 years ago

I spent a crazy amount of time to turn allowSyntheticDefaultImports and esModuleInterop to false, now it takes 11sec to refresh vs 16sec before. Better but still incredibly slow.

shilman commented 3 years ago

@JesusTheHun which framework is your project using? angular?

JesusTheHun commented 3 years ago

@shilman React with TypeScript.

shilman commented 3 years ago

@JesusTheHun Do you have a repro repo you can share?

JesusTheHun commented 3 years ago

@shilman no this is my company's project.

JesusTheHun commented 3 years ago

any chance I can collect some logs/traces ? I quickly tried to activate the debug mode for docgen but didn't yield anything. I didn't search a lot though

JesusTheHun commented 3 years ago

Quick update: when I update/refresh a stateless component it goes a lot faster than when I update a connected component. My intuition is that since I use typesafe-actions to manage fully typed actions, epics and reducers, the docgen plugin need to parse my entire type structure to be able to get mapDispatchToProps types. Ironically I don't use them because I use a mocked store that cast actions('dispatch') instead.

JesusTheHun commented 3 years ago

@shilman is there a way to set the PropFilter plugin parameter in storybook ? I would like to disable the parsing of functions, I believe it may be the thing killing performance in my case.

shilman commented 3 years ago

@JesusTheHun yes: https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration

DiFuks commented 3 years ago

I have the same problem (the build hangs for about 5 seconds at this stage: "70% sealing plugins DocGenPlugin")

With the typescript: {reactDocgen: 'react-docgen'} option enabled, rebuilding is very fast, but almost all types are missing from the document.

With the option enabled: ![Screen_Shot_2021-06-11_at_2 16 35_AM](https://user-images.githubusercontent.com/12777199/121608977-9248a080-ca5b-11eb-9532-efd1b8d0c79a.png)
Without: ![Screen_Shot_2021-06-11_at_2 18 08_AM](https://user-images.githubusercontent.com/12777199/121608988-9a084500-ca5b-11eb-9beb-5594ec05f7d1.png)
DiFuks commented 3 years ago

Args children and icon declare in argTypes. Without this, the props panel is empty

DiFuks commented 3 years ago

main.js:

const path = require('path');
const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
  stories: ['../src/**/__stories__/*.stories.mdx'],
  addons: ['@storybook/addon-docs'],
  core: {
    builder: 'webpack5',
  },
  webpackFinal: (config, { configType }) => {
    if (!config.resolve.plugins) {
      // eslint-disable-next-line no-param-reassign
      config.resolve.plugins = [];
    }

    config.resolve.plugins.push(new TsconfigPathsPlugin());

    const fileLoaderRule = config.module.rules.find(
      (rule) => rule.test && rule.test.test('.svg'),
    );

    fileLoaderRule.exclude = /\.svg$/;

    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack', 'url-loader'],
    });

    if (configType === 'DEVELOPMENT') {
      config.plugins.push(
        new ForkTsCheckerWebpackPlugin({
          eslint: {
            enabled: true,
            files: path.resolve(process.cwd(), './src/**/*.{ts,tsx,mdx,js}'),
          },
          typescript: {
            mode: 'write-references',
          },
        }),
      );
    }

    return config;
  },
};
emadbaqeri commented 3 years ago

@latviancoder what happens when you configure the following setting in .storybook/main.js:

module.exports = {
  typescript: { reactDocgen: 'react-docgen' }
}

This worked for me, great thanks :)

dkrefta commented 1 year ago

omg, this also worked for me:

module.exports = {
  typescript: { reactDocgen: 'react-docgen' }
}

was taking forever to load now it's better than ever, thanks @shilman

UltimateGG commented 1 month ago

Removing the -typescript works but some props are gone, all their defaults and descriptions are no longer inferred from the ts-doc. Is there any better solution to this?