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)
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.
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...