Skip to content

Tailwind CSS v4 Deployment and Optimization — Production Guide

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Tailwind CSS v4 Deployment and Optimization. We cover key concepts, practical examples, and best practices to help you master this topic.

Tailwind CSS v4 deployment focuses on production optimization with Lightning CSS minification, automatic content detection, zero-config purging, and framework-specific deployment strategies for Vite, Next.js, Remix, and static sites.

What You'll Learn

You will learn how to configure production builds, optimize CSS output with Lightning CSS, set up CDN delivery, deploy with various frameworks, and monitor build performance.

Why It Matters

Production CSS bundles directly impact page load time and user experience. DodaTech's v4 production builds average 6KB gzipped per page, achieved through automatic purging and Lightning CSS optimization.

Real-World Use

The DodaTech tutorial site deploys Tailwind v4 via Vite to Netlify, with automatic CSS purging producing a 5.8KB production bundle that serves over 15,000 pages.

flowchart LR
    A[Source CSS] --> B[Tailwind v4 Build]
    B --> C[Content Detection]
    C --> D[Lightning CSS]
    D --> E[Minified CSS]
    E --> F[CDN Deploy]
    B --> G[Purge Unused]
    G --> D
    style B fill:#38bdf8,stroke:#0284c7,color:#fff
    style D fill:#22c55e,stroke:#16a34a,color:#fff

Production Build Configuration

# Install production dependencies
npm install -D @tailwindcss/vite lightningcss

# Build with Vite
npx vite build

# Build with CLI
npx @tailwindcss/cli -i ./src/input.css -o ./dist/output.css --minify

Expected output: Both commands produce optimized CSS bundles. Vite's build integrates with the full framework pipeline. The CLI is suitable for simple static sites.

// vite.config.js — optimized production build
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [tailwindcss()],
  build: {
    cssMinify: "lightningcss",
    minify: "esbuild",
    rollupOptions: {
      output: {
        manualChunks: undefined,
        inlineDynamicImports: true,
      },
    },
    cssCodeSplit: false,
  },
});

Expected output: This configuration uses Lightning CSS for CSS minification (matching Tailwind's internal engine), disables CSS code splitting for single-file output, and uses esbuild for JavaScript minification.

Automatic Content Detection

@import "tailwindcss";

/* v4 detects content paths automatically — no tailwind.config needed */

/* But you can specify content paths explicitly if needed */
@source "./src/**/*.html";
@source "./src/**/*.{js,jsx,ts,tsx}";
@source "!./src/excluded/**";

Expected output: The @source directive tells Tailwind v4 where to scan for class usage. The ! prefix excludes directories. Without @source, v4 scans all files in the project root.

@import "tailwindcss";

/* Multiple source paths for monorepo */
@source "../../packages/ui/src/**/*.tsx";
@source "../docs/**/*.md";
@source "./app/**/*.html";

/* Source with specific extensions */
@source "./src" {
  extensions: ["html", "jsx", "tsx"];
}

Expected output: In Monorepo setups, @source can reference packages outside the current directory. The extensions option restricts which file types are scanned.

CSS Output Optimization

@import "tailwindcss";
@import "tailwindcss/theme" layer(theme);
@import "tailwindcss/preflight" layer(base);
@import "tailwindcss/utilities" layer(utilities);

/* Only the utilities you use are generated — no manual purge config needed */

Expected output: Tailwind v4 automatically generates only the CSS classes detected in the scanned source files. No separate purge or content configuration is required.

@import "tailwindcss";

/* Disable unused layer generation for smaller output */
@config {
  layers: {
    theme: true;
    base: true;
    components: true;
    utilities: true;
  }
}

Expected output: The @config block allows granular control over which CSS layers to include. Disabling unused layers can reduce bundle size further for component libraries.

Framework-Specific Deployment

// Netlify — netlify.toml
[build]
  command = "npm run build"
  publish = "dist"

[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

Expected output: Netlify deploys the Vite output directory. Static assets get immutable cache headers for optimal CDN Caching.

# Vercel — vercel.json
{
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "headers": [
    {
      "source": "/assets/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ]
}

Expected output: Vercel configuration matches Netlify. Both platforms support immutable asset caching for optimal CDN performance.

# Docker multi-stage build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Expected output: The multi-stage Docker build produces a minimal production image (~25MB) with the Tailwind v4 site served by Nginx.

CDN Delivery

<!-- Tailwind v4 CDN for prototyping -->
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

<!-- With specific version -->
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.0.0/dist/cdn.min.js"></script>

Expected output: The CDN script loads Tailwind v4 directly in the browser. Suitable for prototyping but not recommended for production due to runtime overhead.

<!-- Production: preload critical CSS -->
<link rel="preload" href="/assets/main-Bd4eR6.css" as="style">
<link rel="stylesheet" href="/assets/main-Bd4eR6.css">

<!-- Inline critical CSS for above-the-fold content -->
<style>
  /* Inline minimal critical styles */
  .flex { display: flex; }
  .grid { display: grid; }
  .text-center { text-align: center; }
  @media (min-width: 768px) {
    .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
</style>

Expected output: Preloading critical CSS and inlining above-the-fold styles improves Largest Contentful Paint (LCP). The main stylesheet loads asynchronously after the critical CSS is applied.

Common Mistakes

1. Not Setting NODE_ENV=production

Without production mode, Tailwind v4 includes debug information and development-only variants. Always set NODE_ENV=production in CI/CD environments.

2. Forgetting @source Directives in Monorepos

In monorepo setups, Tailwind v4 cannot automatically detect files in sibling packages. Use explicit @source directives for all packages that use Tailwind classes.

3. Not Caching Static Assets

Without Cache-Control: immutable headers, browsers re-request CSS assets on every visit. Configure CDN caching for fingerprinted assets.

4. Using CDN Script in Production

The CDN script processes styles at runtime, adding ~50KB of JavaScript and delaying rendering. Use the build-based approach for production.

5. Missing Build Error Handling

Build errors in CI/CD can fail silently. Add proper error handling and fail-fast mechanisms in deployment scripts.

Practice Questions

  1. How does Tailwind v4 detect which classes to include? It scans source files automatically for class name usage. The @source directive specifies which directories to scan.

  2. What is the role of Lightning CSS in production builds? Lightning CSS minifies the generated CSS, removes unused rules, and applies vendor prefixes, replacing the previous PostCSS-based pipeline.

  3. How do you configure CDN caching for Tailwind assets? Set Cache-Control: public, max-age=31536000, immutable for fingerprinted asset files in your CDN or hosting platform.

  4. What is the @source directive used for? It explicitly tells Tailwind v4 where to scan for class usage, essential in monorepos and projects with non-standard directory structures.

  5. Why avoid the CDN script in production? The CDN script processes styles at runtime, adding JavaScript overhead, delaying rendering, and preventing static optimization.

Challenge

Set up a complete CI/CD pipeline for a Tailwind v4 project that includes: production build with Lightning CSS minification, content scanning across a monorepo with 3 packages, Docker multi-stage build for container deployment, CDN cache headers configuration, and build size monitoring with alerts if CSS exceeds 15KB.

FAQ

Do I need a separate purge step in v4?

No. Tailwind v4 purges unused CSS automatically during build. No separate purge configuration is needed.

What is the difference between Vite and CLI for production?

Vite integrates with the full framework ecosystem (JS bundling, HMR, plugins). CLI is simpler and sufficient for static sites.

How small can a Tailwind v4 production bundle be?

A typical marketing site bundle is 5-10KB gzipped. Component-heavy apps might be 15-25KB. The automatic purging ensures only used classes are included.

Can I deploy Tailwind v4 to Cloudflare Pages?

Yes. Cloudflare Pages supports Vite builds natively. Use npm run build as the build command and dist as the output directory.

Does Tailwind v4 support server-side rendering (SSR) frameworks?

Yes. Tailwind v4 works with Next.js, Remix, Nuxt, SvelteKit, Astro, and other SSR frameworks through their Vite or PostCSS integrations.

Mini Project

Create a deployment pipeline for a Tailwind v4 marketing site with: Vite production build configuration, @source directives for a monorepo with two packages, Docker multi-stage build to Nginx, Netlify deploy configuration with immutable caching, and a build-size check in CI that fails if the CSS bundle exceeds 12KB gzipped.

What's Next

Now apply everything in the Tailwind v4 Project where you will build a complete dashboard from scratch. Then explore CSS for deeper understanding of the foundational technology.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro