grobelDev

Setup Tailwind and PurgeCSS with PostCSS in Create-React-App in 5 Minutes

March 26, 2020

So, you have Tailwind CSS in your application. That’s great! Now you get to reap the benefits of Utility CSS.

But there’s a clear downside here. When you start running analytics on your website, you see that performance has been hit severely.

npm-start

This is as Tailwind CSS is really just an extremely long CSS file.

Even if we are only rendering some simple text, the entirety of the Tailwind CSS file still gets imported.

If only there was a way to selectively use the CSS that you are actually using.

Enter PurgeCSS.

PurgeCSS eliminates all the CSS that you’re not using in your applicaiton. This ensures that the only CSS remaining in your built production website is CSS that is actually being used.

With some configuration with PostCSS, you can make PurgeCSS only run during your build step, ensuring that your development experience is not impacted.

This is as if PurgeCSS is always constantly running, you’ll have to constantly rebuild your development environment any time you make even a minor change to your CSS. This isn’t ideal for a number of reasons which is why we’re setting up the PostCSS configuration.

Here is the final deployed website:
https://react-tailwind-purgecss-zxc6fpw5uq-uc.a.run.app/

Here is the final repository for reference:
https://github.com/grobelDev/react-tailwind-purgecss

Step 1: Setup the initial repository.

Let’s start by creating a directory to hold the project.

mkdir cra-tailwind-purgecss && cd $_

Step 2: Install the necessary packages.

npx create-react-app ./ &&
npm install tailwindcss postcss-cli autoprefixer --save-dev &&
npx tailwind init &&
npm install -D @fullhuman/postcss-purgecss &&
npm audit fix

As an optional step, take out some of the boilerplate create-react-app files:

rm src/App.test.js src/App.css src/index.css src/logo.svg src/serviceWorker.js

Step 3: Create Configuration Files

Let’s create some empty configuration files.

  • ./postcss.config.js
  • ./src/css/tailwind.src.css

Create these files with:

touch postcss.config.js &&
mkdir -p ./src/css &&
touch ./src/css/tailwind.src.css

Step 4: Setup Configuration Files

Let’s put some code into those files.

./postcss.config.js:

const purgecss = require("@fullhuman/postcss-purgecss")({
  content: ["./src/**/*.jsx", "./src/**/*.js", "./public/index.html"],
  css: ["./src/tailwind.css"],
  // Include any special characters you're using in this regular expression
  defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
})

module.exports = {
  plugins: [
    require("tailwindcss"),
    require("autoprefixer"),
    ...(process.env.NODE_ENV === "production" ? [purgecss] : []),
  ],
}

./src/css/tailwind.src.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

Step 5: Final Setup

In package.json, replace the default scripts section:

./package.json:

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "start:css": "postcss src/css/tailwind.src.css -o src/tailwind.css",
    "build:css": "postcss src/css/tailwind.src.css -o src/tailwind.css --env production",
    "prestart": "npm run start:css",
    "prebuild": "npm run build:css"
  },

In /src/index.js, replace the default code to use our generated tailwind.css file:

./src/index.js:

import React from "react"
import ReactDOM from "react-dom"
import "./tailwind.css"

import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))

Step 6: Verify Installation

Done! Everything should be setup now.

Let’s use some Tailwind to verify that everything installed properly.

App.js:

import React from "react"

export default function App() {
  return (
    <div className="text-4xl font-bold text-center text-blue-500">
      Hello World
    </div>
  )
}

Step 7: Verify Performance

So our setup is to use PurgeCSS in production to strip away any extraneous CSS we are not using.

Thus, the expectation is that our performance should be low during development, but high after we build and deploy our application.

npm start should show a webpage with low performance. npm build + deployment should show a webpage with high performance.

So let’s test that.

If we run npm start on our current application, we can run an audit using Chrome’s devtools.

Here is the result: npm-start

Low performance, as expected. Importing the entirety of Tailwind CSS results in significantly lowered performance, even when only rendering ‘Hello World’ in text.

However, let’s now look at a deployed version of the website (after the build step): npm-build

Nice, now our numbers look much better!
This is as we’re only using the CSS that we need. Also, we managed to do this without severely impacting the developer experience.

Here is the final deployed website:
https://react-tailwind-purgecss-zxc6fpw5uq-uc.a.run.app/

Here is the final repository for reference:
https://github.com/grobelDev/react-tailwind-purgecss