Generate multiple CSS files from Tailwind (with Webpack)

I consistently chose Tailwind for styling whenever I had the option. Tailwind’s compatibility and ease of use with any front-end stack are remarkable. I rarely faced a situation where I needed to generate Tailwind CSS classes into separate files within the same project.

However, this did occur while I was developing a WordPress plugin. This plugin required the creation of admin pages in the dashboard and the addition of styles to a few blocks on the front end.

In my WordPress plugin, I always prefer to separate admin features from public features. Consequently, my project had a structure similar to this.

The plugin structure
admin
--- css
------ admin.css
--- js
public
--- css
------ public.css
--- js
my-plugin.php
In the end, I will have an admin.css file that will be loaded in the dashboard and a public.css file that will be loaded on the front end as needed. The content of admin.css should be generated based on the classes used in the files within the admin folder. Similarly, public.css should contain the classes used in the files within the public folder.

Here is what is needed to achieve this goal:

1. Install Tailwind CSS and Webpack

In the plugin directory, execute this code to install the required dependencies.

Recuired npm packages
npm init -y
npm install tailwindcss postcss autoprefixer webpack webpack-cli css-loader postcss-loader mini-css-extract-plugin --save-dev

2. Create Tailwind Config Files

The next step is to create two separate Tailwind CSS configuration files tailwind.admin.config.js and tailwind.public.config.js. This can be done with:

Create Tailwind config files
npx tailwindcss init tailwind.admin.config.js
npx tailwindcss init tailwind.public.config.js

Modify these configuration files to point to their respective content directories. For example

tailwind.admin.config.js
module.exports = {
  content: ['./admin/**/*.{js,php}'],
  theme: {
    extend: {},
  },
  plugins: [],
}
tailwind.public.config.js
module.exports = {
  content: ['./public/**/*.{js,php}'],
  theme: {
    extend: {},
  },
  plugins: [],
}

3. Setup PostCSS Configuration

Create a postcss.config.js file at the root of your project. You will configure it to use Tailwind CSS with the appropriate configuration file based on the environment or some condition.

postcss.config.js
module.exports = ({ file }) => {
  const isAdmin = file.includes('admin');
  return {
    plugins: [
      require('tailwindcss')(isAdmin ? './tailwind.admin.config.js' : './tailwind.public.config.js'),
      require('autoprefixer'),
    ],
  };
};

4. Configure Webpack

webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  entry: {
    admin: './admin/js/admin.js',
    public: './public/js/public.js',
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'), // assuming will be exported to ./dist folder
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: { importLoaders: 1 },
          },
          'postcss-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
    }),
  ],
};

5. Create CSS Entry Points

Create CSS files that will be processed by Webpack and Tailwind CSS for each part of your project.

admin/js/admin.js
import '../css/admin.css';
public/js/public.js
import '../css/public.css';

After that, you should insert Tailwind directives in your CSS files

admin/css/admin.css
@tailwind base;
@tailwind components;
@tailwind utilities;
public/css/public.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Now, running this command should let WebPack to run. It will under the hood run Tailwind (as mentioned in the config) and scan all the .js and .php files in each directory.

Generate the destination files
npx webpack --mode production

Leave a Reply

Your email address will not be published. Required fields are marked *