How to Process Tailwind / PostCSS with Webpack

Usually when I work with webpack another tool I'm using generates the appropriate config for me and I can remain blissfully unaware of how it all works.

With Tanzawa I've only been adding tooling when absolutely necessary. The other day I configured PostCSS and Tailwind with Webpack. It still required a bunch of searching and piecing together blog posts to get something that worked for me.

Below is a list of facts that helped me figure out how to think about processing CSS with webpack.

  • As wrong as it feels, your entry point for processing your CSS should be a Javascript file.
  • Webpack by default does not output a separate stylesheet file. In order to output a plain CSS file, you must use the MiniCssExtractPlugin.
  • Despite wanting to output only CSS, and specifying the filename in the options (style.css), Webpack will create an empty Javascript file regardless. There isn't a way to prevent this unless you add another plugin. I'm adding it to .gitignore.
  • The "use" plugins have the following roles
    • MiniCssExtractPlugin: Exact built css to a dedicated css file.
    • css-loader: Allow you to import css from your entrypoint Javascript file
    • postcss-loader: Run postcss with yourΒ 

// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const tailwindConfig = {
  entry: "./css/index.js",
  output: {
    path: path.resolve(__dirname, "../static/tailwind/"),
  },
  plugins: [
    new MiniCssExtractPlugin({ 
        filename: "style.css"
    }),
  ],
  module: {
   rules: [
    {
      test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: "css-loader", options: { importLoaders: 1 } },
          "postcss-loader",
        ],
    },
   ],
  },
}
module.exports = [tailwindConfig]

In order for postcss to play well with Tailwind and webpack, I needed to update my config to pass the tailwind plugin the path for the tailwind.config.js. It simply imports (requires) the tailwind config and immediately passes the path.

// postcss.config.js
module.exports = {
  plugins: [
    require("tailwindcss")("./tailwind.config.js"),
    require("autoprefixer"),
  ]
}

Finally to run this all for production, I execute via webpack as follows. I still need to figure out how to get the NODE_ENV environment variable set via with the webpack --production flag, so for now it's a bit redundant.

// package.json
{
  ...
  "scripts": {
    "build": "NODE_ENV=production webpack --mode=production"
  }
  ...
}