šØ The Problem
If you've been using Tailwind via CDN in production, then you've been loading the entire Tailwind CSS library into your website, which is awful for user experience. You basically said to your browser:
āHere, take the entire library. Iāll only use like 5% of it, but you figure that out.ā
The CDN version of Tailwind ships everything. Every utility class, every variation, every possible styling option. Itās great for quick prototyping, but in production? Itās overkill.
What does that mean in practice?
- Unnecessary payload: your users download way more CSS than they need
- Slower load times: especially noticeable on weaker networks (which is not exactly rare)
- Zero optimization: no tree-shaking, no purging, just raw bulk
- Not scalable: the more serious your project gets, the worse this decision looks
It works⦠But when it actually comes down to performance, it quietly becomes one of those things you āfix laterā and never do.
š” The Idea
Instead of shipping the entire Tailwind universe to the browser, you flip the approach:
Only generate the styles you actually use.
Hereās the workflow:
- Scan your project files (templates, HTML, JS, etc.)
- Detect the Tailwind classes youāve used
- Compile only those classes into a CSS file
- Output a clean, minimal stylesheet you can serve like any static asset
Thatās it.
No frameworks. No over-engineering. No magic. Maybe a bit of voodoo š.
You end up with:
- A much smaller CSS file
- A faster site
- A setup that works across Django, PHP, Go, or anything else
Itās one of those changes that feels small, but once you use it, going back to CDN starts to feel⦠questionable.
āļø The Setup
This setup uses Node.js purely as a build tool. No React, no Vite, no complex framework setup.
1. Setup Environment
Make sure you have Node.js installed:
node -v
npm -v
Create a workspace for Tailwind:
mkdir tailwind-build
cd tailwind-build
npm init -y
Install dependencies:
npm install tailwindcss postcss autoprefixer @tailwindcss/typography
2. Configure Tailwind
Initialize Tailwind:
npx tailwindcss init
Create your CSS entry file:
mkdir src
touch src/styles.css
Add this to src/styles.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
Set up PostCSS (postcss.config.js):
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
3. Define Content Paths
This is the important part. This tells Tailwind where to look for class names. You can modify it to match your project's template structure.
Update tailwind.config.js:
module.exports = {
content: [
"../**/*.html",
"../**/*.js",
"../**/*.ts",
],
darkMode: "class",
theme: {
extend: {},
},
plugins: [
require("@tailwindcss/typography"),
],
};
This works for:
- Django templates
- PHP files
- Go templates
- basically anything that outputs HTML
4. Build Process
Add scripts to your package.json:
"scripts": {
"dev": "tailwindcss -i ./src/styles.css -o ./dist/tailwind.css --watch",
"build": "tailwindcss -i ./src/styles.css -o ./dist/tailwind.css --minify"
}
You can modify the location of the output file (./dist/tailwind.css) to the exact location you want your output tailwind.css file to be generated.
Run development mode:
npm run dev
This runs the dev compiler that actively watches for changes in your template files.
For production:
npm run build
This minifies the output tailwind.css file so that it is as light as possible.
Your compiled CSS will be in:
dist/tailwind.css
Or whatever location you set it to be.
Move or copy that file into your projectās static/assets folder and link it like normal CSS. Or however you stack links to static files.
š How It Works Behind the Scenes
This is the part most tutorials skip, probably because it requires thinking.
Tailwind doesnāt magically āknowā what styles you need. It literally scans your files.
That content array in your config:
content: [
"../**/*.html",
"../**/*.js",
]
ā¦tells Tailwind:
āGo through these files and collect every class name you can find.ā
So if your templates contain:
<div class="bg-black text-white p-4"></div>
Tailwind will generate only:
bg-blacktext-whitep-4
Everything else? Ignored.
What about unused styles?
Gone.
Tailwindās build process effectively purges anything you didnāt use. No extra configuration needed and no cleanup scripts.
Why this works across frameworks
Tailwind doesnāt care about Django, PHP, or Go.
It only cares about:
- strings in files
- that look like class names
So whether your HTML comes from:
- Django templates
- PHP includes
- Goās
html/template
ā¦itās all the same to Tailwind.
Which is why this setup works everywhere without modification.
Youāve basically turned Tailwind into a very obedient assistant that only does exactly what you asked. No more, no less. A rare trait in both software and humans.
š Works With Any Backend
This setup doesnāt care what backend youāre using. Itās not loyal. It just scans files and does its job.
Django
Point Tailwind to your templates:
<div class="bg-black text-white p-4">
Hello from Django
</div>
After building, only those classes exist in your final CSS. No extras hitching a free ride.
PHP (Blade or Plain PHP)
Same idea:
<div class="bg-blue-500 text-white p-2">
Hello from PHP
</div>
Tailwind doesnāt care if itās Blade, raw PHP, or something held together with hope. It just reads the output files.
Go Templates
Even Go gets to join the party:
<div class="text-green-500 font-bold">
Hello from Go
</div>
As long as your templates live within the paths defined in content, Tailwind will find and compile the classes.
The Point
If your project produces HTML, then this works.
Just files ā scan ā build ā done.
š Production Tips
This is where people quietly sabotage their own setup.
Use
--minify
Your users donāt need nicely formatted CSS. They need fast-loading pages.Donāt run
--watchin production
Unless you enjoy wasting server resources for absolutely no benefit.Cache your static files
Set proper cache headers so browsers donāt keep re-downloading the same CSS file every time. Basic, but often ignored.
If you skip these, youāre basically undoing the performance gains you just worked for.
š¦ GitHub Repo
If you donāt feel like setting this up from scratch (completely fair), Iāve already packaged it:
š https://github.com/brandnova/tailwind-build-pipeline.git
- Ready-to-clone
- Minimal configuration
- No unnecessary complexity
This is the exact setup I use across my recent web projects, regardless of whether Iām working with Django, PHP, or Go.
You can clone it, drop it into your workflow, and move on with your life instead of reconfiguring Tailwind for the hundredth time.
Top comments (1)
Shipping the full Tailwind CDN to production is a massive performance hit. The standalone Tailwind CLI executable is perfect for these non-Node environments. You just point the watcher at your Django templates or Go views and it compiles a tiny stylesheet without needing npm installed anywhere. Keeps the build pipeline brilliantly lightweight.