DEV Community

Stanley Sathler
Stanley Sathler

Posted on

Enabling styled-components' debugging options in your CRA app without ejecting

I have a project using CRA (create-react-app), TypeScript and styled-components.

styled-components has a useful feature when you are developing your components: a debugging option called displayName that shows the components' name in the generated CSS classes. It helps you to identify each component in your DevTools.

According to the docs, to enable it, you need to use a Babel plugin.

The docs says we need a different plugin if we are using TypeScript. However, it is not the case, even if your project uses CRA + TypeScript, as mine does.

However, CRA doesn't have a .babelrc file. It seems that its Babel configuration is given through the webpack config.

It brings another problem: CRA doesn't support a custom webpack config unless you "hack it".

So we need to follow two steps:

  • 1. Find a way to modify CRA's default webpack config.
  • 2. Add the Babel plugin.

Customizing CRA's default webpack config

There is an awesome package called react-app-rewired that allows you to extend the default webpack config.

$ yarn add -D react-app-rewired

You create a file named config-override.js (at the root path) that acts similarly to the webpack config file.

// config-override.js
module.exports = function(config) {
  // `config` is the default config. Do whatever you want.
  return config;
}

If we have the default webpack config, all we have to do now is to find out which rule we should modify to add the extra Babel plugin.

However, there is also a tiny package that makes this task easier: the customize-cra.

Injecting the Babel plugin

The customize-cra package is a set of utility functions that helps you extend some config from CRA. Let's say these functions basically "change the right object properties for you".

$ yarn add -D customize-cra

Then update your config-override.js file to inject the Babel plugin:

const { override, addBabelPlugin } = require('customize-cra')

module.exports = override(
  addBabelPlugin(
    ['babel-plugin-styled-components', {
      displayName: true,
      // any extra config from babel-plugin-styled-components
    }]
  )
)

Updating your dev / build scripts

The final step is simple: you need the modify the default npm scripts in your package.json so they can use config-override.js rather than the default webpack config.

{
  "name": "your-app",
  "version": "0.1.0",
  "private": true,
  // ... omitted for brevity purposes
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject" // No need to change it for `eject` command
  },
}

Conclusion

Well, that's it! ๐Ÿš€ I don't fully understand how webpack works internally, so even this simple thing took me some time to figure out. I hope it helps someone else.

Top comments (2)

Collapse
 
dorshinar profile image
Dor Shinar

Hi, there is a much easier way to accomplish that without resorting to external packages: Babel macros.
And you can use eslint no-restricted-import to force everyone to use the babel macro.

Collapse
 
anniehuang profile image
Annie-Huang

Change to Babel macros will cause all my jest snapshot test failed. It keeps complaining cannot compile, e.g.
TypeError: macro_1.default.li is not a function
github.com/styled-components/style...