Skip to main content
Back to Blog

Laravel Mix Tailwind: Complete Setup Guide, JIT, Purge, HMR, and Production Tips

Laravel Mix Tailwind: Complete Setup Guide, JIT, Purge, HMR, and Production Tips – cover image

Integrating Tailwind CSS into Your Laravel Project Using Laravel Mix

An Optimized Workflow for Development and Production

Welcome! Using Laravel Mix with Tailwind CSS is a powerful combination that streamlines your frontend workflow, enforces consistency, and produces highly optimized assets for production. This guide will walk you through setting up, configuring, and mastering this stack. We'll cover everything from initial installation to best practices for a clean, efficient build process. Let's get started!


Prerequisites: Your Development Toolkit

Before we begin, ensure your development environment meets the following requirements. This setup is crucial for a stable and performant build process.

  • Node.js LTS (18.0+): Required for running Laravel Mix and its dependencies.
  • npm (9.0+): The package manager for Node.js.
  • PHP & Composer: For managing your Laravel project.
  • A Laravel Project (8.0+): You can create a new one or use an existing project.
  • A Code Editor: Visual Studio Code is highly recommended.
  • A Command Line / Terminal: Essential for running commands.

Why This Stack?

Combining Laravel Mix and Tailwind centralizes your entire asset compilation pipeline. You get JavaScript bundling, PostCSS processing with Autoprefixer, Tailwind's JIT engine for instant utility generation, and Mix's versioning for reliable cache-busting—all managed from a single webpack.mix.js file.

Step 1: Project Setup & Dependency Installation

First, let's create a new Laravel application if you don't already have one.

composer create-project laravel/laravel mix-tailwind-demo
cd mix-tailwind-demo

Next, install the necessary frontend dependencies using npm. This includes Laravel Mix, Tailwind CSS, and the required PostCSS plugins.

npm install -D laravel-mix@^6.0.49 tailwindcss@^3.4 postcss@^8 autoprefixer@^10 postcss-import@^15

Now, initialize Tailwind CSS by creating its configuration files. This command generates both tailwind.config.js and postcss.config.js.

npx tailwindcss init -p

Step 2: Configure Tailwind, PostCSS, and Mix

With the files generated, we need to configure them to work together. First, tell Tailwind where to scan for class names in your tailwind.config.js file. This is crucial for the JIT engine and for purging unused styles in production.

// tailwind.config.js
module.exports = {
  content: [
    './resources/views/**/*.blade.php',
    './resources/js/**/*.vue',
    './resources/js/**/*.js',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

Next, ensure your postcss.config.js file loads the necessary plugins in the correct order.

// postcss.config.js
module.exports = {
  plugins: {
    'postcss-import': {},
    tailwindcss: {},
    autoprefixer: {},
  },
};

Finally, update your webpack.mix.js to process your CSS with PostCSS. This configuration also enables source maps for development and versioning for production.

// webpack.mix.js
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
   .postCss('resources/css/app.css', 'public/css', [
      require('postcss-import'),
      require('tailwindcss'),
      require('autoprefixer'),
   ]);

if (mix.inProduction()) {
    mix.version();
} else {
    mix.sourceMaps();
}

Step 3: Create Stylesheet and Integrate into Blade

Create your main stylesheet at resources/css/app.css and add the three main Tailwind directives. These are placeholders that Tailwind will replace with its generated styles.

@tailwind base;
@tailwind components;
@tailwind utilities;

In your main Blade layout file (e.g., resources/views/layouts/app.blade.php), reference the compiled stylesheet and JavaScript using Laravel's mix() helper. This function automatically resolves the correct path for versioned assets.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    ...
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">
    <script src="{{ mix('js/app.js') }}" defer></script>
</head>
<body>
    ...
</body>
</html>

Step 4: Running Development and Production Builds

Your package.json file includes scripts to run your builds. Here are the most important ones:

Development Build: Compile assets once without minification.

npm run dev

Watch for Changes: Automatically recompile assets when you save a file.

npm run watch

Hot Module Replacement (HMR): Instantly inject changes into the browser without a full page refresh.

npm run hot

Production Build: Minify assets, purge unused CSS, and apply versioning for optimal performance.

npm run prod

The difference between development and production builds is significant. A typical unpurged Tailwind file can be over 3MB, while a purged production file is often just 5-15KB.

Conclusion and Best Practices

Congratulations! You've successfully configured a modern frontend workflow with Laravel Mix and Tailwind CSS. This setup provides a fast, efficient development experience and produces highly optimized assets for production.

Here are some best practices to keep your workflow clean and performant:

  • Keep Versions Pinned: To avoid conflicts, stick to a compatible matrix (e.g., Mix 6.x, PostCSS 8.x, Tailwind 3.x).
  • Organize Your CSS: Use Tailwind's @layer directive to group custom component styles and utilities, ensuring they are loaded in a predictable order.
  • Tighten Content Globs: Be specific in your tailwind.config.js content paths to speed up JIT and purge scans.
  • Extract Vendor Libraries: For larger projects, use mix.extract() to split out vendor libraries (like Vue or Axios) into a separate file that can be cached by browsers for longer.
  • Avoid Dynamic Class Names: The JIT engine cannot detect dynamically concatenated class names like 'text-' + color . Always use full, static class names in your templates.

Frequently Asked Questions (FAQ)

What is the benefit of using Laravel Mix with Tailwind CSS?

Laravel Mix centralizes asset compilation in one webpack.mix.js file, making builds predictable. With Tailwind CSS, you get a utility-first workflow, PostCSS processing, Autoprefixer, versioning, and easy production optimizations. It streamlines everything in one place.

How does Tailwind's JIT engine help?

The Just-In-Time (JIT) engine generates utilities on demand as you write them, providing instant feedback in development. It watches your content files and creates only the classes you actually use, which dramatically improves performance and reduces CSS size.

What's the best way to handle cache busting?

Use mix.version() in your production build. It appends unique hashes to compiled filenames, forcing browsers to fetch fresh assets after deployments. Always reference assets with Laravel's mix() helper in your Blade templates.

Why are my Tailwind classes not appearing?

This is usually due to incorrect paths in the content array of your tailwind.config.js file. Double-check that the paths and file extensions match your project structure. Also, ensure the @tailwind directives are present in your main CSS file.

How do I fix PostCSS or Autoprefixer version conflicts?

Align versions with Laravel Mix's requirements: Mix 6 expects PostCSS 8+. Ensure your package.json has compatible versions for tailwindcss, postcss, and autoprefixer. If you encounter errors, delete your node_modules folder and lockfile, then reinstall with npm install.