DEV Community

Drew Town
Drew Town

Posted on • Updated on • Originally published at drewtown.dev

Setting up Tailwind and Purgecss with Gridsome Without Using Any Plugins

View more posts on drewtown.dev

If you haven't heard of Tailwind by now it is a rising star in the utility-first CSS framework space that makes developing with CSS fun and productive. With Tailwind you are no longer fighting against the framework to try and get the box outline blue or the margin between your cards a certain rem size.

Instead, Tailwind gives you the tools and utilities to build unique looking websites by composing the necessary pieces together. There are opportunities still to create a pre-defined .button or .box component. But instead of providing those out of the box Tailwind gives you the flexibility to decide what those defined components should be and how many of them you will need.

When using a utility-based CSS library you are always selecting the parts of the library that you want to take into your project. Adding my-8 shadow-lg rounded-sm to a div means that your project now depends on those classes. But what about my-0 and my-2 and all of the other varieties that come with Tailwind? Without using something like Purgecss your deployed site would need to bring all of those unused classes that Tailwind helpfully provides along for the ride to production. This is sub-optimal as the client is now the server is going to need to ship those bytes and each client will be downloading them.

Even though Tailwind provides many options for various padding, margin, colors and more most likely you'll only be using a fraction of those. With Purgecss we can cut the bloat and do so aggressively by scanning files for instances of those class names and removing those that went unused in any of the templates.

At the time of writing this article the styles for all of drewtown.dev are 3.6KB gzipped while still having access to all of the power of Tailwind when developing. Combining Tailwind and Gridsome is a no-brainer. The speed of a static JAM stack demands and efficient CSS stack to go with it and Tailwind is the answer.

Dependencies

npm i -S @fullhuman/postcss-purgecss tailwindcss
Enter fullscreen mode Exit fullscreen mode

Create a Tailwind Configuration File

Tailwind requires a configuration file that will be used to generate the necessary classes. We need to initialize one and by default it will create a tailwind.js file.

npx tailwind init [optionally provide a file name here]
Enter fullscreen mode Exit fullscreen mode

Importing Tailwind

Once the initializing process is complete we have to import Tailwind into our project. This could be done in your App.vue file but I prefer to create a global.css file. In the global.css file I can create any necessary global components outside the scope of the Gridsome project.

/* global.css */
@tailwind base;
@tailwind components;
/* Add your btn/input/etc components here */
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Import the global.css file into your main.js file.

//main.js
import "./styles/global.css";
Enter fullscreen mode Exit fullscreen mode

Gridsome Configuration

Gridsome provides CSS loader options which is what allows us to hook into the build process without a plugin.

First we must import Tailwind and tell it where to locate the Tailwind configuration file. Next, import Purgecss's Postcss plugin. When we are developing it would be time consuming and unnecessary to run Purgecss. Instead of running it all the time it is possible to conditionally add the purgecss plugin to the postcss plugins array by checking the value of process.env.NODE_ENV for production.

const tailwindcss = require("tailwindcss");
const purgecss = require("@fullhuman/postcss-purgecss");

module.exports = {
  siteName: "The Site Name",
  plugins: [],
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          tailwindcss,
          ...process.env.NODE_ENV === "production" ? [purgecss] : []
        ],
      },
    },
  }
};
Enter fullscreen mode Exit fullscreen mode

Purgecss Configuration

Finally, we need to make a few modifications to Purgecss.

module.exports = {
  content: [
    "./src/**/*.vue",
    "./src/**/*.js",
    "./src/**/*.jsx",
    "./src/**/*.html",
    "./src/**/*.pug",
    "./src/**/*.md",
  ],
  whitelist: ["svg:not(:root).svg-inline--fa"], 
  whitelistPatterns: [/^fa-/, /^svg-inline--fa/], 
  whitelistPatternsChildren: [/^token/, /^pre/, /^code/], 
  defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [] 
};
Enter fullscreen mode Exit fullscreen mode

Content

The content array allows you to specify a series of paths to check for CSS classes. You can be as inclusive or restrictive as necessary.

Extractor

It is required to provide a defaultExtractor to Purgecss that will be able to correctly parse Tailwind classes. Without adding the extractor Purgecss will miss many classes in your template that have dashes or colons in them.

Whitelisting

Sometimes Purgecss can be a bit too aggressive in pruning classes from your CSS files. Usually, this happens with dynamic classes or third party libraries that Purgecss doesn't have access to or are loaded at runtime. It is your responsibility to whitelist these either in the one of the whitelist options available in Purgecss whether that is in the configuration file like the example above, or via a comment in the CSS file.

Wrapping up

At this point Tailwind is loaded into the Gridsome project and all of the many help utilities should be available to make styling your pages a breeze.

Top comments (2)

Collapse
 
skoontastic profile image
skoontastic

Hi Drew, thanks for the article. Used it successfully on a new project.

One thing that I found though, Tailwind changed its config file for v. 1.0 from tailwind.js to tailwind.config.js and actually doesn't need it to be specified on import any longer. So the import for the gridsome.config.js file would look like:

const tailwindcss = require("tailwindcss");

Collapse
 
drewtownchi profile image
Drew Town

Thanks Skoontastic. I can and will definitely go back and update this for 1.0 (hopefully next week). Thanks for reading and the comment!