Skip to main content
Macuin Laravel uses Vite as its frontend build tool, providing fast Hot Module Replacement (HMR) during development and optimized builds for production.

Frontend Stack

The project uses a modern frontend stack configured in package.json:9-16:
"devDependencies": {
  "@tailwindcss/vite": "^4.0.0",
  "axios": "^1.11.0",
  "concurrently": "^9.0.1",
  "laravel-vite-plugin": "^2.0.0",
  "tailwindcss": "^4.0.0",
  "vite": "^7.0.7"
}

Key Dependencies

  • Vite 7.0.7: Lightning-fast build tool and dev server
  • Tailwind CSS 4.0: Utility-first CSS framework
  • Laravel Vite Plugin 2.0: Seamless Laravel integration
  • Axios 1.11: HTTP client for API requests
  • Concurrently 9.0: Run multiple commands in parallel

Vite Configuration

The Vite configuration is defined in vite.config.js:1-27:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
        tailwindcss(),
    ],
    server: {
        host: '0.0.0.0',
        port: 5173,
        strictPort: true,
        origin: 'http://localhost:5173',
        hmr: {
            host: 'localhost',
            port: 5173,
        },
        watch: {
            ignored: ['**/storage/framework/views/**'],
        },
    },
});

Configuration Details

Entry Points (vite.config.js:8)
  • resources/css/app.css - Main stylesheet
  • resources/js/app.js - Main JavaScript bundle
Server Settings (vite.config.js:13-21)
  • Listens on 0.0.0.0:5173 for Docker compatibility
  • HMR configured for localhost:5173
  • Strict port mode enabled
  • Ignores Laravel’s view cache directory
The refresh: true option automatically reloads the browser when Blade templates change.

Docker Node Service

The Node.js development server runs in a Docker container defined in docker-compose.yml:58-68:
node:
  image: node:22-alpine
  container_name: laravel_node
  working_dir: /var/www/html
  user: "0:0"
  volumes:
    - ./:/var/www/html
    - node_modules:/var/www/html/node_modules
  ports:
    - "5173:5173"
  command: sh -lc "chown -R 1000:1000 /var/www/html/node_modules && npm ci || npm i && npm run dev -- --host 0.0.0.0 --port 5173 --strictPort"

Container Features

  • Image: Node.js 22 Alpine (lightweight)
  • Port Mapping: 5173:5173 for Vite dev server
  • Volume: Separate node_modules volume for performance
  • Auto-start: Automatically installs dependencies and starts dev server
The Node container handles file permissions automatically, ensuring compatibility between host and container environments.

NPM Scripts

Defined in package.json:5-8:
npm run dev

Script Details

ScriptCommandPurpose
devviteStart development server with HMR
buildvite buildBuild optimized assets for production

JavaScript Structure

The JavaScript entry point is minimal and modular: resources/js/app.js (resources/js/app.js:1-2)
import './bootstrap';
resources/js/bootstrap.js (resources/js/bootstrap.js:1-5)
import axios from 'axios';
window.axios = axios;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

Global Objects

  • window.axios: Configured Axios instance with CSRF protection
  • Includes X-Requested-With header for Laravel AJAX detection

Hot Module Replacement

1

Start Docker Services

Ensure Docker containers are running:
docker-compose up -d
2

Verify Node Container

The Node container automatically starts Vite:
docker-compose logs node
You should see:
VITE v7.0.7  ready in XXX ms

➜  Local:   http://localhost:5173/
➜  Network: http://0.0.0.0:5173/
3

Include Vite Directives

Add to your Blade templates:
<!DOCTYPE html>
<html>
<head>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
4

Develop with HMR

Edit files in resources/css/ or resources/js/ and see changes instantly in your browser without full page reloads.
The Vite dev server must be accessible at http://localhost:5173 for HMR to work. Ensure port 5173 is not blocked by firewalls.

Asset Compilation

Development Mode

Vite serves assets directly from source with fast HMR:
# Via Docker (automatic)
docker-compose up node

# Or manually
npm run dev

Production Build

Generate optimized, versioned assets:
npm run build
This creates:
  • Minified JavaScript bundles
  • Optimized CSS with purged unused styles
  • Hashed filenames for cache busting
  • Manifest file for Laravel integration
Output location: public/build/

Development Workflow

The complete development workflow uses Composer’s dev script (composer.json:43-46):
composer dev
This runs concurrently:
  1. PHP Server: php artisan serve
  2. Queue Worker: php artisan queue:listen
  3. Log Viewer: php artisan pail
  4. Vite Dev Server: npm run dev
The concurrently package provides colored output for each service, making it easy to monitor all processes.

Troubleshooting

HMR Not Working

Issue: Changes don’t reflect in browser Solutions:
  • Verify Node container is running: docker-compose ps node
  • Check Vite dev server is accessible: curl http://localhost:5173
  • Ensure @vite directive is in your Blade template
  • Clear browser cache

Port Already in Use

Issue: Port 5173 is already in use Solutions:
  • Stop other Vite instances: docker-compose down
  • Kill process on port 5173: lsof -ti:5173 | xargs kill
  • Change port in vite.config.js (update both port and hmr.port)

Node Modules Permission Errors

Issue: Permission denied in node_modules Solutions:
  • Rebuild Node container: docker-compose up --build node
  • The container automatically fixes permissions on startup
  • Ensure the named volume is properly mounted

Next Steps

Styling

Learn about the CSS architecture and Tailwind configuration

Deployment

Build and deploy assets for production

Build docs developers (and LLMs) love