skip to content

Storybook 7.0 + React.js + TailwindCSS + CSS modules + Typescript setup that #$%& works

/ 3 min read

UPDATE: when writing this I have found THIS article, that, coincidentally, was also updated around the same time.

<rant>

Setting up a storybook project should NOT be THAT hard. I mean, everyone uses Storybook, it’s the only viable option out there when working on a design system.

TailwindCSS is at the stage when it’s already gained the momentum. Even large companies are considering it. Practically EVERY front-end dev has already worked with it.

And CSS modules have beed out there for more that 6 years I believe. And even though in JavaScript terms it’s a dinosaur, a legacy, it’s very much not dead and still a top choice for many, including moi.

Not even going to say anything about Typescript and React. If you’re not using TS or never worked with TS today - you’re unemployable. And React is a standard.

Surely there should be an article somewhere on how to set all this up correctly. SURELY?!

</rant>

Well, after 4 hours of googling and trial and error, I finally was able to crack this “OH SO UNUSUAL” tech stack setup. Here is the repo, and let me highlight two points.

Point 1: Webpack 5 builder and framework

Webpack 4 is still the default choice for Storybook, but Storybook has already released support for Webpack 5, so I see no reason why we’d stick to v4. Important note here is that since we’re updating the core property, we should also update the framework

main.ts
export default {
framework: '@storybook/react-webpack5',
core: {
builder: '@storybook/builder-webpack5',
},
}

Point 2: Don’t overwrite default Webpack rules, but add more instead

It (unfortunately!) became a habit for whatever reason, that if I need to add some custom loader, I exclude the default rule from the array and re-create it. We shouldn’t do that, because it messes up the Storybook config in a way that it becomes hard to unfuck it.

Because we need to add a PostCSS loader to our .css files, don’t try to re-create css rule with all the css-loader and style-loader etc., but just push that extra rule to the end of that array, and be done with it.

main.ts
export default {
...
webpackFinal: async config => {
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: { tailwindcss: {}, autoprefixer: {} },
},
},
},
],
include: path.resolve(__dirname, '../'),
})
return config
},
...
}

That’s pretty much all I wanted to say. Those two points took me a while to understand, so hope your found my post within your first hour of searching. 😅