Tailwind CSS Purge: Optimize Angular for Production

Remove unused Tailwind CSS utilities from your Angular production build for best performance

Authors
Marc Stammerjohann Marc Stammerjohann
Published at

By design, Tailwind CSS generates a large amount of utility classes for your development build. For your Angular application you want the best performance by only including the classes you are actually using in your production build. Tailwind got you covered! PurgeCSS is build-in making it easy to tree-shake unused Tailwind styles for your application.

You are going to learn how to setup Tailwind's purge option to optimize Tailwind CSS in your Angular and for your Scully Jamstack application.

The purge options in this post have been tested with Angular 11 and Tailwind CSS 2.0, it also works with Angular 10 and Tailwind CSS 1.9.

Get Started

Get ready with a new or existing Angular + Tailwind CSS application

ng new app-name

# add tailwind
ng add ngx-tailwind

# optional - add jamstack with Scully
ng add @scullyio/init

Now use Tailwind CSS utility classes in your Angular application HTML template, using apply in your stylesheets or even in your TypeScript files via @HostBinding(...).

Purge unused Tailwind CSS utilities in Angular

Tailwind provides a purge option in the tailwind.config.js file. Purge removes only classes generated by Tailwind or styles added to the @layer directive. Custom CSS or third-party CSS like Angular Material or Prism.js will not be removed.

Simply provide all your template paths as an array to the purge option. For an Angular application this would be all HTML and TS files in your src directory. TS files should be included as they might reference class names using e.g. @HostBinding(...).

module.exports = {
  purge: ["./src/**/*.html", "./src/**/*.ts"],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Use *.{html,ts} to match multiple file types in the same directory

module.exports = {
- purge: ["./src/**/*.html", "./src/**/*.ts"],
+ purge: ["./src/**/*.{html,ts}"],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Trigger Tailwind to automatically purge your CSS by setting NODE_ENV=production during your ng build step. If you used ngx-tailwind schematics to setup Tailwind it automatically added a production script to your package.json. Additionally, the latest release of ngx-tailwind@1.1.0 adds the above purge options automatically to your tailwind.config.js.

{
  "scripts": {
    "build:prod": "NODE_ENV=production ng build --prod"
  }
}

Now run npm run build:prod to only include used Tailwind CSS utilities in your Angular production build. This even works great in your Scully application

Advanced Purge options

purge also accepts an options object for further optimizations. Available purge options are enabled, content for your template paths, preserveHtmlElements, layers, mode and last options to pass it directly to PurgeCSS. The defaults for these options are:

module.exports = {
  purge: {
    // enabled: true, // enabled by `NODE_ENV=production` or enable manually
    mode: 'layers', // or 'all' ☠️ be careful
    preserveHtmlElements: true, // or false ⚠️ not generally recommended
    layers: ['base', 'components', 'utilities'], // remove layers to ignore from purging
    content: [], // add your template paths
    options: { /* PurgeCSS options */}
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Too use the object syntax for the purge option add the template paths to the content option

module.exports = {
  purge: {
    content: ["./src/**/*.{html,ts}"]
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Go ahead and provide additional options to the purge object to further optimize your production build based on your application. For specific configurations pass it directly to PurgeCSS using the options key. You can provide safelist, blocklist, extractors and more.

module.exports = {
  purge: {
    content: ["./src/**/*.html", "./src/**/*.ts"],

    // These options are passed through directly to PurgeCSS
    options: {
      safelist: ['bg-red-500', /^mat-/],
      blocklist: ['bg-orange-500', /^cdk-/],
      extractors: [],
      ...
    }
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Let's improve purging for a Scully application by writing an extractor for your Markdown content files to detect which HTML tags and CSS classes are actually used.

Purge Scully Markdown content

Scully organizes the content of your static-site in Markdown files. Add the path to your Markdown files e.g. './blog/**/*.md' to the content array. Create an extractor targeting only files with the Markdown extension md.

module.exports = {
  purge: {
    content: ['./src/**/*.{html,ts}', './blog/**/*.md'],
    options: {
      extractors: [
        {
          extensions: ['md'],
          extractor: (content) => {

            return [];
          },
        },
      ],
    },
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Before matching HTML elements and CSS classes you need to parse the Markdown content to HTML. Scully uses marked to parse your Markdown content files. Let's require it in the tailwind.config.js and parse the content in the extractor.

const marked = require('marked');

module.exports = {
  purge: {
    content: ['./src/**/*.{html,ts}', './blog/**/*.md'],
    options: {
      extractors: [
        {
          extensions: ['md'],
          extractor: (content) => {
            content = marked(content);

            return [];
          },
        },
      ],
    },
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Let's use the Regex used by blog.tailwindcss.com to find all used HTML elements and classes. Also set the mode: 'all' ☠️ and preserveHtmlElements: false ⚠️ to remove unused tags like h4 and more.

const marked = require('marked');

module.exports = {
  purge: {
    model: 'all',
    preserveHtmlElements: false,
    content: ['./src/**/*.{html,ts}', './blog/**/*.md'],
    options: {
      extractors: [
        {
          extensions: ['md'],
          extractor: (content) => {
            content = marked(content);

            // Capture as liberally as possible, including things like `h-(screen-1.5)`
            const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || []

            // Capture classes within other delimiters like .block(class="w-1/2") in Pug
            const innerMatches =
              content.match(/[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g) || []

            return broadMatches.concat(innerMatches);
          },
        },
      ],
    },
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

Perfect, now your Angular or Scully applications are optimized for production and you are ready to deploy it to Firebase Hosting or other services.

Sponsor us

Did you find this post useful? We at notiz.dev write about our experiences developing Apps, Websites and APIs and develop Open Source tools. Your support would mean a lot to us 🙏. Receive a reward by sponsoring us on Patreon or start with a one-time donation on GitHub Sponsors.

Table of Contents

Top of Page Comments Related Articles

Related Posts

Find more posts like this one.

Authors
Marc Stammerjohann
October 17, 2022

Codegen REST API types and requests for Angular

Automatic code generation from OpenAPI 3 for Angular
Angular NestJS Read More
Authors
Marc Stammerjohann
July 08, 2022

Maizzle: Craft beautiful HTML emails with Tailwind CSS

Send beautiful HTML emails via NestJS crafted with Maizzle and Tailwind CSS
Maizzle Tailwind CSS NestJS Read More
Authors
Gary Großgarten
September 23, 2021

Media Queries with RxJS

Media Queries | Practical examples with RxJS
RxJS Angular Read More
Authors
Marc Stammerjohann
November 09, 2020

Firebase Hosting: Preview and Deploy via GitHub Actions

Preview and Deploy your Angular or Scully app on Firebase Hosting automated via GitHub Actions
Firebase Angular GitHub Read More
Authors
Marc Stammerjohann
October 29, 2020

Jamstack: Angular + Scully + Tailwind CSS

Use Angular's static site generator Scully and style it with Tailwind CSS
Scully Angular Tailwind CSS Read More
Authors
Marc Stammerjohann
June 03, 2021

Angular with Tailwind CSS

Learn how to style Angular applications with Tailwind CSS
Angular Tailwind CSS CSS Read More
Authors
Marc Stammerjohann
May 28, 2020

Floating Form Field with Tailwind CSS

Learn how to build a floating form field with Tailwind CSS
Tailwind CSS CSS Read More
Authors
Gary Großgarten
March 25, 2020

Angular Elements: Create a Component Library for Angular and the Web

Publish Angular components and Custom Elements from a single project! Using the Angular CLI.
Angular Web Components Read More

Sign up for our newsletter

Sign up for our newsletter to stay up to date. Sent every other week.

We care about the protection of your data. Read our Privacy Policy.