Storybook: Error processing Flow optional object spread caused by babel-plugin-react-docgen even though shared .babelrc

Created on 27 Nov 2018  路  10Comments  路  Source: storybookjs/storybook

Describe the bug
When running storybook on a react app using flow, an optional spread type [1] causes an error [2] and storybook fails to compile.
The code runs finein the application even though storybook uses App's babel and .babelrc.
The error comes from:babel-plugin-react-docgen

To Reproduce
Steps to reproduce the behavior:
I have created a CRA with storybook demo exhibiting this behavior.

  1. Go to https://github.com/maikthomas/storybook-flow-optional-spread-type-error
  2. Clone, install and run as described in readme.
  3. See error in storybook, and not in app.

Expected behavior
A clear and concise description of what you expected to happen.
Storybook should process the code with babel without breaking.

System:

  • OS: MacOS
  • Device: Macbook Pro 2017
  • Browser: chrome
  • Framework: react
  • Version: 4.0.9

Additional context
Add any other context about the problem here.
Example optional spread type [1] :
This is valid flow: https://flow.org/try/#0C4TwDgpgBAQghgJ3gLygXigbwD4CgpQBGiAXFAM7AICWAdgOYA0+RcyZlNDu2AvgNy5coSFABiAewkB5BJInwkbdFjwEAZlI5U6TFgDpDAfkUoeAoQGMJtSlE0Sy82fNPKMmB2QDkD7xetbYHspYgRidnEpFyk3VA8vKF8pb0ZWBB8w1NZI7wj-QSA

type OptionalProps = {|
  bar: string,
  baz: string
|};

type Props = {|
  foo: string,
  ...?OptionalProps
|};

Error [2] : Can see in stack trace that this comes from babel-plugin-react-docgen
I can confirm that removing babel-plugin-react-docgen from storybook's webpack rules fixes this.

ERROR in ./src/optional-spread-type.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: Property elements[0] of ArrayExpression expected node to be of a type ["null","Expression","SpreadElement"] but instead got undefined
    at validate (/spread-type-test/node_modules/@babel/types/lib/definitions/utils.js:148:13)
    at validator (/spread-type-test/node_modules/@babel/types/lib/definitions/utils.js:97:7)
    at Object.validate (/spread-type-test/node_modules/@babel/types/lib/definitions/utils.js:172:7)
    at validate (/spread-type-test/node_modules/@babel/types/lib/validators/validate.js:17:9)
    at builder (/spread-type-test/node_modules/@babel/types/lib/builders/builder.js:46:27)
    at Object.ArrayExpression (/spread-type-test/node_modules/@babel/types/lib/builders/generated/index.js:232:31)
    at buildObjectExpression (/spread-type-test/node_modules/babel-plugin-react-docgen/lib/index.js:123:14)
    at buildObjectExpression (/spread-type-test/node_modules/babel-plugin-react-docgen/lib/index.js:108:60)
    at /spread-type-test/node_modules/babel-plugin-react-docgen/lib/index.js:81:19
    at Array.forEach (<anonymous>)
    at injectReactDocgenInfo (/spread-type-test/node_modules/babel-plugin-react-docgen/lib/index.js:73:17)
    at PluginPass.exit (/spread-type-test/node_modules/babel-plugin-react-docgen/lib/index.js:42:11)
    at newFn (/spread-type-test/node_modules/@babel/traverse/lib/visitors.js:193:21)
    at NodePath._call (/spread-type-test/node_modules/@babel/traverse/lib/path/context.js:53:20)
    at NodePath.call (/spread-type-test/node_modules/@babel/traverse/lib/path/context.js:40:17)
    at NodePath.visit (/spread-type-test/node_modules/@babel/traverse/lib/path/context.js:97:8)
 @ ./src/stories/index.js 6:0-57 13:29-47
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/core/dist/server/config/polyfills.js ./node_modules/@storybook/core/dist/server/config/globals.js ./.storybook/config.js ./node_modules/webpack-hot-middleware/client.js?reload=true
babel / webpack compatibility with other tools cra has workaround inactive question / support

Most helpful comment

For anyone running into this, here's a solution that seems to work well for me (strip out the babel-plugin-react-docgen from Storybook's webpack config). Thanks to @maikthomas for the suggestion/inspiration https://github.com/storybooks/storybook/issues/4873#issuecomment-458497220

// .storybook/webpack.config.js

// See docs: https://storybook.js.org/configurations/custom-webpack-config/
// Curious about debugging this? Try console.dir(config, {depth: null});
// See https://storybook.js.org/docs/configurations/custom-webpack-config/#debug-the-default-webpack-config

const isDocGenPlugin = plugin =>
  Array.isArray(plugin) &&
  typeof plugin[0] === 'string' &&
  plugin[0].includes('react-docgen');

module.exports = ({config}) => {
  // Strip out the babel-plugin-react-docgen
  // This crashes Storybook when using certain Flow features 馃檭
  // See https://github.com/storybooks/storybook/issues/4873#issuecomment-458497220
  const babelLoader = config.module.rules[0].use[0];
  babelLoader.options.plugins = babelLoader.options.plugins.filter(
    plugin => !isDocGenPlugin(plugin)
  );

  // Push on additional rules (support .scss)
  config.module.rules.push({
    test: /[.](css|scss)$/,
    use: ['style-loader', 'css-loader', 'sass-loader'],
  });

  return config;
};

Storybook would crash for me with an error:

ERROR in ./src/scripts/components/SomeComponent.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: Property elements[0] of ArrayExpression expected node to be of a type ["null","Expression","SpreadElement"] but instead got undefined
    at validate (PROJECT_ROOT/node_modules/@babel/types/lib/definitions/utils.js:148:13)
    at validator (PROJECT_ROOT/node_modules/@babel/types/lib/definitions/utils.js:97:7)
    at Object.validate (PROJECT_ROOT/node_modules/@babel/types/lib/definitions/utils.js:172:7)
    at validate (PROJECT_ROOT/node_modules/@babel/types/lib/validators/validate.js:17:9)
    at builder (PROJECT_ROOT/node_modules/@babel/types/lib/builders/builder.js:46:27)
    at Object.ArrayExpression (PROJECT_ROOT/node_modules/@babel/types/lib/builders/generated/index.js:237:31)
    at buildObjectExpression (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:122:14)
    at buildObjectExpression (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:107:60)
    at PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:80:19
    at Array.forEach (<anonymous>)
    at injectReactDocgenInfo (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:72:17)
    at PluginPass.exit (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:41:11)
    at newFn (PROJECT_ROOT/node_modules/@babel/traverse/lib/visitors.js:193:21)
    at NodePath._call (PROJECT_ROOT/node_modules/@babel/traverse/lib/path/context.js:53:20)
    at NodePath.call (PROJECT_ROOT/node_modules/@babel/traverse/lib/path/context.js:40:17)
    at NodePath.visit (PROJECT_ROOT/node_modules/@babel/traverse/lib/path/context.js:97:8)
 @ ./src/scripts/components/SomeComponent-stories.js 11:0-58 20:29-47
 @ ./src/scripts sync [-.]?stories\.js$
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true

...anytime I would attempt using types such as:

// @flow
import * as React from 'react';
import {AnotherComponent} from './AnotherComponent';

// SomeComponent props API extends, but slightly differs from AnotherComponent
export function SomeComponent(props: {
  someProp: string,
  anotherProp: string,
  ...$Exact<React.ElementConfig<typeof AnotherComponent>>,
  overRidePropFromAnotherComponent: string,
}) {/* ... */}

... even though Flow and our actual webpack output outside Storybook were behaving as expected.

FWIW I'm running into this with versions:

  • React 16.8.4
  • @storybook/*: 5.0.1
  • Flow 0.94.0

All 10 comments

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!

Hopefully this doesn't get closed. I think the core issue is that the code is being processed by babel-plugin-react-docgen before getting properly transpiled by other babel modules. (or something like that). Particularly annoying since I never asked to use babel-plugin-react-docgen...
Maybe just ensuring the code is transpiled with app babel config first?

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!

Hi again, I'd really like to keep this from going inactive. I gave a clear example of how to reproduce with an bare minimum example repo.
The tags of CRA & question/support aren't really what I'd hope for.
CRA - incidental, it was the easiest way for me to repro the issue, we don't use CRA in our real app.
Question/Support - I'm really inclined to think this is a bug and not a support issue (albeit a low priority bug for other people)

We have had to use quite an ugly hack to have our app work where we manually remove the babel-plugin-react-docgen plugin from the storybook babel config object before pushing our own rules.

Also seeing this issue. Would be great to have a fix.

@maikthomas @kelchm It's a heavy-handed solution, but you can completely override the webpack config in Storybook: https://storybook.js.org/configurations/custom-webpack-config/

I'm overhauling the info addon which uses the docgen after v5 ships https://github.com/storybooks/storybook/issues/1147, so I'll try to take a look at this then. Happy to take a PR for this in the meantime if anybody is interested in tackling the problem directly.

For anyone running into this, here's a solution that seems to work well for me (strip out the babel-plugin-react-docgen from Storybook's webpack config). Thanks to @maikthomas for the suggestion/inspiration https://github.com/storybooks/storybook/issues/4873#issuecomment-458497220

// .storybook/webpack.config.js

// See docs: https://storybook.js.org/configurations/custom-webpack-config/
// Curious about debugging this? Try console.dir(config, {depth: null});
// See https://storybook.js.org/docs/configurations/custom-webpack-config/#debug-the-default-webpack-config

const isDocGenPlugin = plugin =>
  Array.isArray(plugin) &&
  typeof plugin[0] === 'string' &&
  plugin[0].includes('react-docgen');

module.exports = ({config}) => {
  // Strip out the babel-plugin-react-docgen
  // This crashes Storybook when using certain Flow features 馃檭
  // See https://github.com/storybooks/storybook/issues/4873#issuecomment-458497220
  const babelLoader = config.module.rules[0].use[0];
  babelLoader.options.plugins = babelLoader.options.plugins.filter(
    plugin => !isDocGenPlugin(plugin)
  );

  // Push on additional rules (support .scss)
  config.module.rules.push({
    test: /[.](css|scss)$/,
    use: ['style-loader', 'css-loader', 'sass-loader'],
  });

  return config;
};

Storybook would crash for me with an error:

ERROR in ./src/scripts/components/SomeComponent.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: Property elements[0] of ArrayExpression expected node to be of a type ["null","Expression","SpreadElement"] but instead got undefined
    at validate (PROJECT_ROOT/node_modules/@babel/types/lib/definitions/utils.js:148:13)
    at validator (PROJECT_ROOT/node_modules/@babel/types/lib/definitions/utils.js:97:7)
    at Object.validate (PROJECT_ROOT/node_modules/@babel/types/lib/definitions/utils.js:172:7)
    at validate (PROJECT_ROOT/node_modules/@babel/types/lib/validators/validate.js:17:9)
    at builder (PROJECT_ROOT/node_modules/@babel/types/lib/builders/builder.js:46:27)
    at Object.ArrayExpression (PROJECT_ROOT/node_modules/@babel/types/lib/builders/generated/index.js:237:31)
    at buildObjectExpression (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:122:14)
    at buildObjectExpression (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:107:60)
    at PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:80:19
    at Array.forEach (<anonymous>)
    at injectReactDocgenInfo (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:72:17)
    at PluginPass.exit (PROJECT_ROOT/node_modules/babel-plugin-react-docgen/lib/index.js:41:11)
    at newFn (PROJECT_ROOT/node_modules/@babel/traverse/lib/visitors.js:193:21)
    at NodePath._call (PROJECT_ROOT/node_modules/@babel/traverse/lib/path/context.js:53:20)
    at NodePath.call (PROJECT_ROOT/node_modules/@babel/traverse/lib/path/context.js:40:17)
    at NodePath.visit (PROJECT_ROOT/node_modules/@babel/traverse/lib/path/context.js:97:8)
 @ ./src/scripts/components/SomeComponent-stories.js 11:0-58 20:29-47
 @ ./src/scripts sync [-.]?stories\.js$
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true

...anytime I would attempt using types such as:

// @flow
import * as React from 'react';
import {AnotherComponent} from './AnotherComponent';

// SomeComponent props API extends, but slightly differs from AnotherComponent
export function SomeComponent(props: {
  someProp: string,
  anotherProp: string,
  ...$Exact<React.ElementConfig<typeof AnotherComponent>>,
  overRidePropFromAnotherComponent: string,
}) {/* ... */}

... even though Flow and our actual webpack output outside Storybook were behaving as expected.

FWIW I'm running into this with versions:

  • React 16.8.4
  • @storybook/*: 5.0.1
  • Flow 0.94.0

Hi, I just ran into a similar issue. Thanks for this report, it helped me.

As a workaround I have hidden the Flow definition from Babel using a comment type include:

/*::
type Props = {
  ...
}
*/

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!

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

Was this page helpful?
0 / 5 - 0 ratings