Storybook: Using a custom .babelrc in create-react-app

Created on 10 Apr 2019  路  27Comments  路  Source: storybookjs/storybook

Describe the bug
I am using customize-cra to add a specific babel plugin for development and I have also added a .babelrc in the .storybook folder which has the following:

{
  "presets": ["react-app"],
  "plugins": ["@babel/plugin-proposal-optional-chaining"]
}

The issue is it doesn't read the babel config even though the terminal says:
image

But in the end it shows the following issue:
image

Expected behavior
It should run the plugins and presets from the custom .babelrc file

System:

  • OS: MacOS
  • Device: Macbook
  • Browser: Chrome
  • Framework: React
  • Version:
    @storybook/react: 5.0.6
    react-scripts: 2.1.8
babel / webpack cra has workaround question / support todo

Most helpful comment

Hi,

If you are using CRA and you need a custom config (like a babel plugin) you can use react-app-rewired with customize-cra.

Here's how you can add the emotion css props plugin to both CRA + Storybook.

(This is useful for Emotion because the babel macro can't setup the emotion css pragma, so really the babel plugin is required)

Step 1

Add customize CRA + React-app-rewired

yarn add customize-cra react-app-rewired --dev
  /* ./package.json */

  "scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test --env=jsdom",
+   "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts eject"
}

Step 2: customize the CRA config:

/* ./config-overrides.js */

const {
  override,
  addBabelPreset
} = require("customize-cra");
const path = require("path");

module.exports = override(
  addBabelPreset("@emotion/babel-preset-css-prop")
);

Step 3: customize the Storybook config:

Note, you can keep using the CRA storybook preset

/* ./storybook/webpack.config.js */

module.exports = ({ config }) => {
  return require("../config-overrides")(config);
};

This way you don't have to duplicate the config overrides, and can use the same overrides for both CRA and Storybook to keep them in sync.

All 27 comments

I am having the same issue.

Obviously the .babelrc in .storybook is completely overriding the CRA config, rather than extending it. Hypothetically, you could use the .babelrc's "extends" property, but I'm not sure where CRA's .babelrc is located (or if it even has one).

@mrmckeb I think the CRA babel heuristic is overriding the user's babelrc. Should we merge them instead?

https://github.com/storybooks/storybook/blob/next/app/react/src/server/framework-preset-cra.js#L29

@shilman, I think it's not a good idea as then we allow people to potentially build a component that works in Storybook, but doesn't work in their actual application.

Can @ryan-ds and/or @acnebs provide insight into what you're trying to achieve here? What features do you want to use in Storybook that are not in Create React App and why? :)

@mrmckeb I need to add a babel plugin (babel-plugin-emotion).

I have components in my CRA that break in Storybook (where I want to test them / hack on them in isolation) as they utilize syntax provided by babel-plugin-emotion.

I add babel-plugin-emotion to the CRA babel config using customize-cra and the addBabelPlugin helper function. But I can't see anything that would allow me to do this with Storybook.

@acnebs That makes sense... But I should point out that the recommend way would be to use the macro.
https://emotion.sh/docs/babel-macros

If you really want to modify the config and use customize-cra, you'll need to modify the Webpack config. If so, let me know and I can give you some more detailed instructions on how to do that - or share your project and I can take a look this weekend :)

@mrmckeb Unfortunately the specific feature I'm using (and one that I don't think I can avoid using) still requires the babel plugin, even with macros support.

So any tips you can provide to customize my webpack config would be very helpful! I really only need to add this one babel plugin at the moment, otherwise the default config works great.

@acnebs Not a problem - sorry for the delay, I started a new job last week and am still a little busy.

If you add a custom webpack config, you'll be able to modify the rules in there.

You can see here that we add CRA's config for TypeScript when it's needed, and you could effectively use the same approach.
https://github.com/storybooks/storybook/blob/next/app/react/src/server/cra-config.js#L196

When you find the rule that you need (using search perhaps), you can then add the babel plugin you need into that rule. It won't look so neat, but it will work for you without breaking the CRA behavour we've designed here.

Again, if you can share your project, I'd be happy to create a PR too (this weekend).

I think @shilman is right and we should improve the base behaviour... I'm just not sure what's best. We don't want that Storybook behaves differently than CRA. The CRA team never recommend using tools like rewired for the obvious reason that we can't support every configuration, but I'm also very aware that this is necessary at times.

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!

@mrmckeb Thanks for the thorough talk-through, that is now what I've done and it is working well.

There is some potential to have a lib like customize-cra that would provide a cleaner API than modifying the config object directly.

I actually tried to use customize-cra for this purpose, as I thought Storybook was using CRA behind the scenes, but for some reason it appears that the config object is structured slightly differently than the default CRA config, to the point where customize-cra was not able to find the rule it was looking for.

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!

@acnebs could you share your solution? I'm trying to get the same thing working on my end with @babel/plugin-proposal-optional-chaining.

Same setup. I'm trying to upgrade to CRA3 and my storybook webpack.config.js that was adding jsx-control-statements is no longer working.

@auderer @thejuan

Fair warning, my solution is far from elegant, but it works. Here's a gist.

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!

Quick comment to prevent stale bot from closing the issue. Is consideration still being given to baking this into Storybook so workarounds don't have to be used?

Related issue #7340

the config posted by @acnebs doesn't seem to work for my ts + CRA + storybook setup.

I've got import { css } from '@emotion/core'; in my tsx files, but it still gives me css="[object Object]"

@JamesYFC I'm not using TS so that could be breaking it. All I can say is it works for me and allows me to use css from @emotion/core.

@acnebs yeah my guess is TS.

~For me, the macro + manual pragma for the base css stuff worked with emotion + storybook, But trying to use components made with import styled from '@emotion/styled/macro'; didn't give me the styles from styled(MyReactComponent), though it worked with the basic stuff like styled('div').~

Nevermind about the styled bit, you just need to ensure you have className in your props for the React component and pass it down where you want into your jsx accordingly.

Hi all,

The preset for CRA is designed to work with CRA, which does not support this - and will soon. We're waiting on TS 3.7.

At that stage, this won't be a problem.

In the meantime, we're working on a new preset which will allow you to extend the Babel config in CRA for Storybook.

@mrmckeb TS3.7 is out -- any updates on this?

Not yet @shilman, I'm checking now to see why the release is still held up.

Is the preset available anywhere ? I was looking for it after I saw your posthttps://github.com/storybookjs/storybook/issues/7340#issuecomment-560101242

Can you confirm the CRA preset won't work in its current state ?

@MeisterTea https://www.npmjs.com/package/@storybook/preset-create-react-app working fine

Nevermind, it works fine, see https://github.com/storybookjs/storybook/issues/7340#issuecomment-561259773

This issue can be closed imo

Hi,

If you are using CRA and you need a custom config (like a babel plugin) you can use react-app-rewired with customize-cra.

Here's how you can add the emotion css props plugin to both CRA + Storybook.

(This is useful for Emotion because the babel macro can't setup the emotion css pragma, so really the babel plugin is required)

Step 1

Add customize CRA + React-app-rewired

yarn add customize-cra react-app-rewired --dev
  /* ./package.json */

  "scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test --env=jsdom",
+   "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts eject"
}

Step 2: customize the CRA config:

/* ./config-overrides.js */

const {
  override,
  addBabelPreset
} = require("customize-cra");
const path = require("path");

module.exports = override(
  addBabelPreset("@emotion/babel-preset-css-prop")
);

Step 3: customize the Storybook config:

Note, you can keep using the CRA storybook preset

/* ./storybook/webpack.config.js */

module.exports = ({ config }) => {
  return require("../config-overrides")(config);
};

This way you don't have to duplicate the config overrides, and can use the same overrides for both CRA and Storybook to keep them in sync.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shilman picture shilman  路  3Comments

rpersaud picture rpersaud  路  3Comments

tomitrescak picture tomitrescak  路  3Comments

alexanbj picture alexanbj  路  3Comments

dnlsandiego picture dnlsandiego  路  3Comments