11 KiB
11 KiB
Laravel + Vue.js + Vue Router Setup Guide
Panduan lengkap untuk setup Laravel dengan Vue.js 3, Vue Router, dan Tailwind CSS menggunakan Vite.
Prerequisites
- PHP >= 8.1
- Composer
- Node.js >= 16.x
- NPM atau Yarn
Step 1: Instalasi Laravel
# Buat project Laravel baru
composer create-project laravel/laravel project-name
# Masuk ke directory project
cd project-name
# Setup environment
cp .env.example .env
php artisan key:generate
Step 2: Instalasi Dependencies Frontend
# Install Vue.js dan dependencies
npm install vue@latest vue-router@latest
# Install Vite plugins
npm install --save-dev @vitejs/plugin-vue
# Install Tailwind CSS
npm install --save-dev tailwindcss@latest @tailwindcss/vite
# Install utilities
npm install --save-dev axios concurrently
Package.json Final
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"@tailwindcss/vite": "^4.0.0",
"@vitejs/plugin-vue": "^6.0.1",
"axios": "^1.11.0",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^2.0.0",
"tailwindcss": "^4.0.0",
"vite": "^7.0.4"
},
"dependencies": {
"vue": "^3.5.19",
"vue-router": "^4.5.1"
}
}
Step 3: Konfigurasi Vite
Buat/update vite.config.js
:
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import tailwindcss from "@tailwindcss/vite";
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: ["resources/css/app.css", "resources/js/app.js"],
refresh: true,
}),
tailwindcss(),
vue()
],
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
},
},
});
Step 4: Setup Tailwind CSS
Buat tailwind.config.js
:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
],
theme: {
extend: {},
},
plugins: [],
}
Update resources/css/app.css
:
@import 'tailwindcss';
Step 5: Struktur Folder Frontend
Buat struktur folder berikut di resources/js/
:
resources/js/
├── components/
│ └── App.vue
├── pages/
│ ├── Home.vue
│ ├── About.vue
│ └── Contact.vue
├── router/
│ └── index.js
└── app.js
Step 6: Setup Vue Router
resources/js/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../pages/Home.vue'
import About from '../pages/About.vue'
import Contact from '../pages/Contact.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/contact',
name: 'Contact',
component: Contact
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
resources/js/app.js
import { createApp } from 'vue';
import router from './router';
import App from './components/App.vue';
const app = createApp(App);
app.use(router);
app.mount('#app');
Step 7: Buat Vue Components
resources/js/components/App.vue
<template>
<div id="app">
<nav class="bg-blue-600 shadow-lg">
<div class="max-w-7xl mx-auto px-4">
<div class="flex justify-between h-16">
<div class="flex space-x-8">
<router-link
to="/"
class="flex items-center px-3 py-2 text-white hover:text-blue-200"
:class="{ 'border-b-2 border-white': $route.name === 'Home' }"
>
Home
</router-link>
<router-link
to="/about"
class="flex items-center px-3 py-2 text-white hover:text-blue-200"
:class="{ 'border-b-2 border-white': $route.name === 'About' }"
>
About
</router-link>
<router-link
to="/contact"
class="flex items-center px-3 py-2 text-white hover:text-blue-200"
:class="{ 'border-b-2 border-white': $route.name === 'Contact' }"
>
Contact
</router-link>
</div>
</div>
</div>
</nav>
<main class="max-w-7xl mx-auto py-6 px-4">
<router-view />
</main>
</div>
</template>
<script setup>
// Main app component
</script>
resources/js/pages/Home.vue
<template>
<div class="home">
<div class="text-center">
<h1 class="text-4xl font-bold text-gray-800 mb-8">Welcome Home</h1>
<div class="bg-yellow-100 border-2 border-yellow-300 rounded-lg p-8 max-w-md mx-auto">
<p class="text-2xl font-bold text-gray-800">{{ message }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const message = ref("Hello from Vue.js!")
</script>
resources/js/pages/About.vue
<template>
<div class="about">
<h1 class="text-3xl font-bold text-gray-800 mb-6">About Us</h1>
<div class="bg-green-50 border border-green-200 rounded-lg p-6">
<p class="text-lg text-gray-700 mb-4">
This is our about page built with Laravel and Vue.js!
</p>
<button
@click="showMore = !showMore"
class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition duration-200"
>
{{ showMore ? 'Show Less' : 'Learn More' }}
</button>
<div v-show="showMore" class="mt-4 p-4 bg-white rounded border">
<p class="text-gray-600">
We're passionate about creating amazing web applications using modern technologies
like Laravel, Vue.js, and Tailwind CSS.
</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const showMore = ref(false)
</script>
resources/js/pages/Contact.vue
<template>
<div class="contact">
<h1 class="text-3xl font-bold text-gray-800 mb-6">Contact Us</h1>
<div class="max-w-md mx-auto bg-white shadow-md rounded-lg p-6">
<form @submit.prevent="submitForm" class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Name</label>
<input
v-model="form.name"
type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input
v-model="form.email"
type="email"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Message</label>
<textarea
v-model="form.message"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 h-24"
required
></textarea>
</div>
<button
type="submit"
class="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-200"
>
Send Message
</button>
</form>
<div v-if="submitted" class="mt-4 p-3 bg-green-100 border border-green-300 rounded text-green-700">
✅ Thank you for your message!
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const form = reactive({
name: '',
email: '',
message: ''
})
const submitted = ref(false)
const submitForm = () => {
console.log('Form submitted:', form)
submitted.value = true
// Reset form after 3 seconds
setTimeout(() => {
submitted.value = false
Object.assign(form, { name: '', email: '', message: '' })
}, 3000)
}
</script>
Step 8: Update Laravel Views
resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Laravel + Vue.js</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="bg-gray-50">
<div id="app"></div>
</body>
</html>
Step 9: Setup Laravel Routes (SPA)
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
// SPA Route - catch all and return main view
Route::get('/{any}', function () {
return view('welcome');
})->where('any', '.*');
Step 10: Jalankan Development Server
# Terminal 1 - Laravel server
php artisan serve
# Terminal 2 - Vite dev server
npm run dev
Atau gunakan concurrently (jika sudah diinstall):
# Install concurrently jika belum
npm install --save-dev concurrently
# Tambahkan script di package.json
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "concurrently \"php artisan serve\" \"vite\""
}
# Jalankan keduanya sekaligus
npm run serve
Struktur Project Final
project-name/
├── app/
├── resources/
│ ├── css/
│ │ └── app.css
│ ├── js/
│ │ ├── components/
│ │ │ └── App.vue
│ │ ├── pages/
│ │ │ ├── Home.vue
│ │ │ ├── About.vue
│ │ │ └── Contact.vue
│ │ ├── router/
│ │ │ └── index.js
│ │ └── app.js
│ └── views/
│ └── welcome.blade.php
├── routes/
│ └── web.php
├── package.json
├── vite.config.js
├── tailwind.config.js
└── composer.json
Testing
Buka browser dan kunjungi:
http://localhost:8000
- Home pagehttp://localhost:8000/about
- About pagehttp://localhost:8000/contact
- Contact page
Troubleshooting
Error: "Component provided template option but runtime compilation is not supported"
- Pastikan
vue
alias sudah ditambahkan divite.config.js
Error: "Failed to parse source for import analysis"
- Pastikan
@vitejs/plugin-vue
sudah terinstall dan ditambahkan di plugins
CSS tidak loading
- Pastikan
@vite
directive sudah benar di blade file - Check jika Tailwind config sudah benar
Router tidak bekerja
- Pastikan Laravel routes catch-all sudah ditambahkan
- Check browser console untuk error JavaScript
Next Steps
- Tambahkan authentication
- Implementasikan API endpoints
- Setup state management (Pinia/Vuex)
- Tambahkan testing (Vitest)
- Deploy ke production
Selamat! Anda telah berhasil setup Laravel + Vue.js + Vue Router! 🎉