How I reduced Tailwind CSS Home Page's HTML size by 28.5%, CSS by 23.7% and JS by 8.4%
Tags: tailwindcss, css, frontend, opensource
Published: 2024-03-11 14:32:56

I really love Tailwind CSS! It's impressive to see how easily Tailwind has made it possible to integrate any project's design system into the code while optimizing the CSS simultaneously.

Tailwind's approach to styling has resulted in very small CSS files. However, as a consequence, the HTML and JS files have become larger.

[Breezify](https://github.com/glebgorokhov/breezify) is my attempt to address this issue.

## How It Works

Breezify is a Node.js library that post-processes your CSS, HTML, and JS files in your build folder, updating them through AST (Abstract Syntax Tree) transformations in a few steps:

1. It identifies class names in your CSS files and `<style>` tags in your HTML files.

2. Breezify then generates a list of ultra-short class names, such as `.a`, `.b`, `.ab`, etc., and creates a mapping that links your existing class names to these new ones. _Did you know that you only need 2 symbols to generate **3328** unique class names?_

3. Afterwards, it updates the class names found in your CSS, HTML, and JS files to these new ones.

Breezify offers a simple mode that replaces everything using regex, but its default mode employs AST transformations, which are smarter and offer more control over what gets updated and what doesn't.

So, in essence, Breezify converts this:

```html
<div class="w-full max-w-content px-6 md:px-9 grid mx-auto z-[1] relative gap-x-6 md:gap-x-10 gap-y-6 md:gap-y-10 grid-cols-1 md:grid-cols-2 justify-items-start items-start">
  <a
    href="#"
    class="gap-2 items-center mb-10 transition-all text-theme-text-interactive dark:text-dark-text-interactive group-hover:text-theme-text-interactive-hover hover:text-theme-text-interactive-hover dark:hover:text-dark-text-interactive-hover dark:group-hover:text-dark-text-interactive-hover"
  >
    Carts
  </a>
</div>
```

into this:

```html
<div class="a b c d e f g h i j k l m n o p">
  <a href="#" class="q r s t u v y z A B">
    Carts
  </a>
</div>
```

And this:

```js
const mySpecialClass = "primary-color";
const decorated = "decorated";

const header = document.querySelector(
  `.header[role='decorated']:not(.decorated) .aside, ${decorated}, aside > .aside, ${mySpecialClass}`,
);
```

into this:

```js
const mySpecialClass = "a";
const decorated = "b";

const header = document.querySelector(
  `.c[role='decorated']:not(.b) .d, ${decorated}, aside > .d, ${mySpecialClass}`,
);
```

Note how the word "decorated" is updated when it appears as a string, but remains unchanged when it is used as the name of a constant or as a value of the "role" attribute.

## How to Use Breezify

1. `npm i breezify` to install the module.
2. `breezify init` to create a configuration file.
3. `npm run build` (or your preferred build command) to build your project.
4. `breezify do` to run Breezify.

For more information, visit the [project's README](https://github.com/glebgorokhov/breezify).

## Testing Breezify with the Tailwind CSS Homepage

The testing process is straightforward.

### 1. Clone Breezify

[Clone the repository](https://github.com/glebgorokhov/breezify) and install dependencies with `pnpm install`.

### 2. Add Files for Testing

Create a folder in `breezify/tests/data/build-files` for your build files and place your files there.

I will create a folder named `tailwind-complete` and save the Tailwind homepage by simply saving the page from the browser:

![Tailwind CSS Homepage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/diufc2y0x7s4de23wlq8.png)

To check how it looks after such a straightforward saving, I can serve this folder using `npx serve tailwind-complete`:

![That's not bad](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i648qimxxknym9aihb5s.png)

![Some pictures are missing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwgri19of6jxsb3ozuq1.png)

_Some pictures are missing._

As you can see, it works; however, some pictures are missing, but that's not an issue for testing purposes.

### 3. Run the Test

Then, I run `pnpm test`, which creates a copy of this folder in `tests/data/output-files/%BUILD_FOLDER_NAME%` and logs all the file size reductions in your terminal:

![My terminal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9idprvcy7jb7xv5roqcv.png)

Breezify reduced the size of HTML files by 28.55%, CSS files by 23.70%, and JS files by 8.44%. Not bad for already minified and obfuscated files, isn't it?

### 4. Preview the Results

Finally, we can preview the results by using `npx serve tailwind-complete` in the `tests/data/output-files` folder:

![Preview Screenshot 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs2na0oznj3xl93yyvdk.png)

![Preview Screenshot 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j929fy5pztvncy2whm89.png)

Interestingly, all images in the "breezified" version are functioning! Aside from the HTML, everything else appears the same:

![New HTML](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/su256pbw2s5tydqwvg58.png)

## Conclusion

Breezify appears to be a valuable addition to the suite of post-processing libraries designed to minimize project file sizes as much as possible.

However, it does have a few drawbacks:

1. It is written in JavaScript, meaning it may not be as fast as if it were developed in, for example, Rust.

2. There is a risk of inadvertently replacing the wrong value, but this is [preventable](https://github.com/glebgorokhov/breezify?tab=readme-ov-file#debugging).

3. There is a possibility of AST (Abstract Syntax Tree) parsing errors.

4. Not all frameworks solely output CSS, JS, and HTML files. I am currently experiencing some difficulties making it work with Next.js, as it produces gzipped files that are challenging to process. However, I am confident this issue can be resolved. Feel free to [contribute](https://github.com/glebgorokhov/breezify?tab=readme-ov-file#contributing) if you have a solution!

Thank you for reading! I can't wait to hear your thoughts on Breezify. Please feel free to share your experiences and results:

- [Breezify Chat on Telegram](https://t.me/breezifychat)
- [Contact me on Telegram](https://t.me/ververy)
- [Follow me on X](https://twitter.com/glebgorokhov)
- [Join the r/breezify subreddit](https://www.reddit.com/r/breezify/)