storybook + tailwind + nuxt one webpack config
Tags: storybook, tailwindcss, nuxt
Published: 2020-05-03 02:20:49

At [Vue Montreal](https://vuemontreal.org) we are using  nuxt a lot.

Today i want to share with you something i feel it will help you as us. We wanted to add storybook to our project.

Everytime i had to create a webpack just for using storybook. And i faced a lot of bugs. And more when i wanted to use tailwind + postcss ^^.

So let's say you have a basic nuxt config with tailwind

So you should have:
- '@nuxtjs/tailwindcss' in your buildModules
- in your assets/css/tailwind.css
```js
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
```
And that's all.

Now you want to implement storybook.
You want to add tailwind so postcss and not creating a new webpack or at least create another full configuration...

You have to create 

```
.storybook/main.js
.storybook/preview.js
```

.storybook/preview.js

```js
import Vue from 'vue'
import { configure } from '@storybook/vue'
import '@/assets/css/tailwind.css'

Vue.component('nuxt-link', {
  props:   ['to'],
  methods: {
    log() {
      action('link target')(this.to)
    },
  },
  template: '<a href="#" @click.prevent="log()"><slot>NuxtLink</slot></a>',
})

configure(require.context('../components', true, /\.stories\.js$/), module);
```
It's basic. I Added nuxt-link for not having some bug because storybook don't know about nuxt-link.
As you see i added import `'@/assets/css/tailwind.css'`.

and the most impostant.

.storybook/main.js

```js
const { getWebpackConfig } = require('nuxt')

module.exports = {
    // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.
    webpackFinal: async (sbWebpack, { configType }) => {

        const nuxtWebpack = await getWebpackConfig('client', {
            for: process.env.NODE_ENV === 'production' ? 'build' : 'dev'
        })

        const recomposedWebpackConfig = {
            mode: nuxtWebpack.mode,
            devtool: nuxtWebpack.devtool,
            entry: sbWebpack.entry,
            output: sbWebpack.output,
            bail: sbWebpack.bail,
            module: {
                rules: [
                    ...nuxtWebpack.module.rules.map(el => {
                        const reg = RegExp(el.test);
                        if (reg.test(".postcss") || reg.test(".css")) {
                            el.oneOf = el.oneOf.map(e => {
                                e.use.push({
                                    loader: 'postcss-loader',
                                    options: {
                                        ident: 'postcss',
                                        plugins: [
                                        require('tailwindcss')('./tailwind.config.js'),
                                        require('autoprefixer'),
                                        ],
                                    },
                                })
                                return e;
                            })
                        }
                        return el;
                    })
                ]
            },
            plugins: sbWebpack.plugins,
            resolve: {
                extensions: nuxtWebpack.resolve.extensions,
                modules: nuxtWebpack.resolve.modules,
                alias: {
                    ...nuxtWebpack.resolve.alias,
                    ...sbWebpack.resolve.alias,
                },
            },
            optimization: sbWebpack.optimization,
            performance: {
                ...sbWebpack.performance,
                ...nuxtWebpack.performance
            }
        }

        return recomposedWebpackConfig;
    },
};

```
The 'problem' here is you need some of storybook webpack and nuxt webpack. So i decided to recompose a webpack config
 with [storybook custom webpack](https://storybook.js.org/docs/configurations/custom-webpack-config/).

And [THIS](https://github.com/nuxt/nuxt.js/pull/7029). A new feature from nuxt that expose nuxt webpack config with `getWebpackConfig`. It return a promise and it's a valid webpack export as you can export promise now too [INFO HERE](https://webpack.js.org/configuration/configuration-types/#exporting-a-promise).

The most important part for you here is:

```js
module: {
 rules: [
  ...nuxtWebpack.module.rules.map(el => {
    const reg = RegExp(el.test);
    if (reg.test(".postcss") || reg.test(".css")) {
      el.oneOf = el.oneOf.map(e => {
       e.use.push({
        loader: 'postcss-loader',
        options: {
         ident: 'postcss',
         plugins: [
          require('tailwindcss')('./tailwind.config.js'),
          require('autoprefixer'),
         ],
        },
      })
      return e;
     })
    }
    return el;
   })
  ]
},
```

What you need to update are `.postcss` and `.css` rules.

And that's it! Now you should be able to write tailwind / postcss in your component with "ONE CONFIG" :).

This is my workaround. Maybe it's not the best so tell me in comments.

ps: An [ISSUE](https://github.com/nuxt-community/tailwindcss-module/issues/71) in @nuxtjs/tailwind about adding support with storybook.