Kasir/DOC-FRONTEND.md
2025-08-27 16:32:02 +07:00

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 page
  • http://localhost:8000/about - About page
  • http://localhost:8000/contact - Contact page

Troubleshooting

Error: "Component provided template option but runtime compilation is not supported"

  • Pastikan vue alias sudah ditambahkan di vite.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! 🎉