How to setup react shared components in monorepo with tailwind, webpack and npm workspace
Tags: monorepo, tailwindcss, webpack, react
Published: 2021-10-18 01:18:09

[Previously](https://dev.to/ynwd/how-to-setup-postcss-tailwind-react-and-webpack-from-scratch-2o6c), we have integrated tailwind and react using webpack. Now we will try to apply it to shared components in monorepo.

```
.
├── package.json
└── web
    ├── components
    │   ├── babel.config.js
    │   ├── package.json
    │   ├── postcss.config.js
    │   ├── src
    │   │   ├── Button.js
    │   │   ├── Header.js
    │   │   ├── index.css
    │   │   ├── index.js
    │   │   └── stories
    │   ├── tailwind.config.js
    │   └── webpack.config.js
    └── modules
        ├── home
        │   └── package.json
        └── root
            ├── src
            │   ├── App.js
            │   └── index.js
            └── package.json
```

clone our previous branch: https://github.com/ynwd/monorepo/tree/storybook

install postcss & tailwind packages
```
npm i postcss postcss-cli postcss-import postcss-loader tailwindcss autoprefixer autoprefixer cssnano mini-css-extract-plugin -D
```

Update webpack config
```js
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const devMode = process.env.NODE_ENV !== "production"

module.exports = {
    mode: devMode ? "development" : "production",
    entry: {
        index: { import: "./src/index.js" }
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: "babel-loader",
            },
            {
                test: /\.css$/i,
                use: [
                    devMode ? "style-loader" : MiniCssExtractPlugin.loader,
                    'css-loader',
                    "postcss-loader",
                ],
            },
        ],
    },
    output: {
        filename: "components.bundle.min.js",
        library: 'fstrComponents',
        libraryTarget: 'umd',
        clean: true
    },
    plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
}

```

Create postcss config
```js
module.exports = {
    plugins: [
        require('postcss-import'),
        require('tailwindcss'),
        require('autoprefixer'),
        require('cssnano')({
            preset: 'default',
        }),
    ],
};
```

Create tailwind config
```js
module.exports = {
  purge: [
    './src/**/*.js',
  ],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
}
```

Create tailwind entrypoint
```css
/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
```

Create custom components
```js
/* src/Button.js */
import React from "react"

export const Button = ({ text = "" }) => {
    return (
        <button className="p-2 pl-5 pr-5 bg-red-500 text-gray-100 text-lg rounded-lg focus:border-4 border-blue-300">
            {text}
        </button>
    )
}
```

```js
/* src/Header.js */
import React from "react"

export const Header = ({ text = "" }) => {
    return (
        <div className="bg-blue-300 mx-auto max-w-sm shadow-lg rounded-lg overflow-hidden">
            <div className="sm:flex sm:items-center px-6 py-4">
                <img className="block h-16 sm:h-24 rounded-full mx-auto mb-4 sm:mb-0 sm:mr-4 sm:ml-0" src="https://avatars.githubusercontent.com/u/10122431?s=400&v=4" alt="" />
                <div className="text-center sm:text-left sm:flex-grow">
                    <div className="mb-4">
                        <p className="text-xl leading-tight">John Doe</p>
                        <p className="text-sm leading-tight text-grey-dark"> {text} </p>
                    </div>
                </div>
            </div>
        </div>
    )
}
```

Update react entry point. We import css file also.
```js
/* src/index.js */
import { Button } from "./Button"
import { Header } from "./Header"
import "./index.css"

export {
    Button,
    Header
}
```

Update `web/components/package.json` script
```json
{
   ...
  "scripts": {
    "build": "NODE_ENV=production webpack",
    "build-watch": "webpack --watch",
    "test": "echo \"Error: no test specified\" && exit 1",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook"
  },
  ...
}
```

Compile
```
npm run build
```

Go to app root dir.
```
cd ../../
```
And don't forget to link the built package. 
```
npm install
```

## Import react-tailwind components

Update root module entry point. Import generated css from components.
```js
/* web/modules/root/src/index.js */
import React from 'react'
import ReactDOM from 'react-dom'
import "@fstr/components/dist/index.css"
import App from './App'
import reportWebVitals from './reportWebVitals'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

```

Update react app
```js
/* web/modules/root/src/App.js */
import { Header, Button } from "@fstr/components"

function App() {
  return (
    <div>
      <Header text="from root" />
      <Button text="my button" />
    </div>
  )
}

export default App
```

Still in the app root folder, run this to see the changes
```
npm start -w @fstr/root
```

You can see the final source code on this branch: https://github.com/ynwd/monorepo/tree/tailwind