Laravel 11 e Vue.js: installazione, configurazione ed esempi
Laravel 11 e vue.js è una combinazione ottimale per scrivere codice pulito ed efficiente.
In questo tutorial vediamo insieme come installare, configurare e sviluppare in laravel 11 utilizzando la potenza di vue.js.
Per provare vue.js scriveremo codice per gestire l’entità di Dato “Posts di un Blog”.
6 minuti
L’esempio descritto in questo articolo, è un esempio di configurazione laravel tutorial vue.js, ed è disponibile su Github.
Installazione vue.js
Configureremo il framework Laravel 11, installeremo il framework JavaScript Vue.js e lo faremo funzionare con Vite. Quindi caricheremo il nostro primo componente Vue.
composer create-project --prefer-dist laravel/laravel crud-spa
Configuriamo i dettagli del DataBase:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<DATABASE NAME>
DB_USERNAME=<DATABASE USERNAME>
DB_PASSWORD=<DATABASE PASSWORD>
Dopo l’installazione di Laravel, procediamo a installare Laravel Breeze.
NON è necessario Breeze per utilizzare vue.js. È solo una preferenza personale: non lo useremo per il sistema di autenticazione e non utilizzeremo la sua versione vue, è solo per un design visivo semplice e veloce, quindi rimuoveremo molte delle sue parti.
composer require laravel/breeze --dev
php artisan breeze:install blade
Per semplicità, creiamo solo una pagina pubblica per Dashboard, rimuoveremo quindi tutti i collegamenti dalla navigazione in cui viene chiamata l’autenticazione. Sia nel menu desktop che mobile.
Il file resources/views/layouts/navigation.blade.php
diventa:
<nav x-data="{ open: false }" class="bg-white border-b border-gray-100">
<!-- Primary Navigation Menu -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex">
<!-- Logo -->
<div class="shrink-0 flex items-center">
<a href="{{ route('dashboard') }}">
<x-application-logo class="block h-9 w-auto fill-current text-gray-800" />
</a>
</div>
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-nav-link>
</div>
</div>
<!-- Hamburger -->
<div class="-me-2 flex items-center sm:hidden">
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out">
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
<!-- Responsive Navigation Menu -->
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
<div class="pt-2 pb-3 space-y-1">
<x-responsive-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-responsive-nav-link>
</div>
</div>
</nav>
Nel file delle routes web.php
, abbiamo bisogno di una sola rotta per la pagina indice e può essere solo una vista. La CRUD per le rotte utilizzerà la vue-router
.
Il file routes/web.php
diventa:
<?php
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('dashboard');
})->name('dashboard');
Adesso dobbiamo specificare il momento in cui Vue verrà “montato”. Cioè l’elemento principale della struttura HTML, dove Vue vivrebbe “al suo interno”. Di solito, è uno degli elementi div principali nel layout principale e per identificarlo gli assegniamo id=”app”.
Quindi apriamo il file resources/views/layouts/app.blade.php e aggiungiamo l’attributo nel primo div dopo l’apertura del body:
.
.
.
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100" id="app">
@include('layouts.navigation')
<!-- Page Heading -->
@isset($header)
<header class="bg-white shadow">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
</header>
@endisset
.
.
.
Configurazione laravel vue.js tutorial
Per impostazione predefinita, Breeze aggiunge Alpine.js, che però non utilizzeremo. Quindi modifichiamo il package.json, presente in root di laravel, e togliemo Alpine.js.
Nella sezione devDependencies
di package.json, togliamo la riga
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.2",
"alpinejs": "^3.4.2",
"autoprefixer": "^10.4.2",
"axios": "^1.6.4",
"laravel-vite-plugin": "^1.0",
"postcss": "^8.4.31",
"tailwindcss": "^3.1.0",
"vite": "^5.0"
}
}
Ora possiamo installare Vue e Vue loader e configurare Vue.
npm install vue vue-loader
Successivamente, dobbiamo installare il plugin Vue Vite.
npm install --save-dev @vitejs/plugin-vue
E modifichiamo il file vite.config.js
presente in root di laravel, come segue:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
},
},
});
Creazione componente vue
Aggiungiamo un componente vue nella pagina Dashboard. In futuro mostrerà l’elenco dei post, quindi chiameremo il suo tag HTML <posts-index>.
Modifichiamo il file resources/views/dashboard.blade.php come segue:
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
{{ __("You're logged in!") }}
<posts-index></posts-index>
</div>
</div>
</div>
</div>
</x-app-layout>
Sostituendo {{ __("You're logged in!") }}
con <posts-index></posts-index>
.
Ora procediamo a creare il componente Vue resources/js/components/Posts/Index.vue. Per ora inseriremo al suo interno solo testo statico fittizio.
Modifichiamo il file resources/js/components/Posts/Index.vue:
<template>
Table coming soon.
</template>
Ogni componente Vue è costituito da due parti:
<script>
<template>
In questo caso, non stiamo ancora eseguendo alcuna operazione JS, quindi non avremo la parte dello script, ma solo il template
.
Ora, tornando all’elemento id="app"
, procediamo a inizializzare un’app Vue, aggiungiamo il componente dall’alto e lo montiamo su quell’elemento dell’app. Tutto ciò deve essere fatto nel file principale resources/js/app.js
. Per impostazione predefinita con Breeze, il file app.js contiene codice utilizzando Alpine.js, e per scelta di implementazione, lo rimuoviamo.
Il file resources/js/app.js diventa:
import './bootstrap';
import { createApp } from 'vue'
import PostsIndex from './components/Posts/Index.vue'
createApp({})
.component('PostsIndex', PostsIndex)
.mount('#app')
Nel file app.js definiamo l’applicazione Vue con createApp()
, importandola preventivamente Alleghiamo un componente all’applicazione Vue, importandolo preventivamente e dandogli il nome PostIndex
.
Montiamo l’applicazione Vue sull’elemento #app
dal layout principale.
In questo modo stiamo denominando il componente PostIndex
in modo da sapere che è un componente per i Post ed è un file Index.vue
.
Per chiamare i componenti nei file Vue, ci sono due modi:
- Quello che abbiamo usato noi è il
kebab-used
. - E in secondo luogo, utilizzando
PascalCase
.
Vue.js supporta entrambi i casi. Quindi per la denominazione dei componenti utilizziamo PascalCase.
Ora compiliamo il tutto utilizzando npm run dev
o npm run build
, quando terminato, apriamo la pagina sul browser e avremo dovremmo vedere il testo Table coming Soon
, come segue:
Ricompilazione JS e Tailwind
Quando lavoriamo con qualsiasi file front-end, dobbiamo ricompilare dopo ogni modifica per vedere le modifiche nel browser. Dobbiamo quindi eseguire npm run build
ogni volta dopo una piccola modifica, o ancora meglio eseguire npm run dev e mantenerlo in esecuzione in background.
Quando eseguiamo npm run dev
con Vite, dopo ogni ricompilazione il browser verrà aggiornato automaticamente. Dopo aver eseguito npm run dev
nella tua console vedrai un risultato simile al seguente:
Dopo npm run build
a video avremo:
Esempio
Proviamo ora con una semplice modifica nel file Vue: aggiungiamo una semplice tabella statica (per ora) al componente PostIndex Vue
.
L’esempio descritto è disponibile su Github.
Quindi il file resources/js/components/Posts/Index.vue
diventa:
<template>
<div class="overflow-hidden overflow-x-auto p-6 bg-white border-gray-200">
<div class="min-w-full align-middle">
<table class="min-w-full divide-y divide-gray-200 border">
<thead>
<tr>
<th class="px-6 py-3 bg-gray-50 text-left">
<span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">ID</span>
</th>
<th class="px-6 py-3 bg-gray-50 text-left">
<span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Title</span>
</th>
<th class="px-6 py-3 bg-gray-50 text-left">
<span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Content</span>
</th>
<th class="px-6 py-3 bg-gray-50 text-left">
<span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Created at</span>
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 divide-solid">
<tr>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">1</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">A</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">Poe switched his focus to prose, and spent the next several years working for literary journals and periodicals, becoming known for his own style of literary criticism. His work forced him to move between several cities, including Baltimore, Philadelphia, and New York City. In 1836, when he was 27, he married his 13-year-old cousin, Virginia Clemm. She died of tuberculosis in 1847. In January 1845, he published his poem "The Raven" to instant success. He planned for years to produce his own journal The Penn, later renamed The Stylus. But before it began publishing, Poe died in Baltimore in 1849, aged 40, under mysterious circumstances. The cause of his death remains unknown, and has been variously attributed to many causes including disease, alcoholism, substance abuse, and suicide.</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">2024-06-01 13:43:47</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">2</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">B</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">Poe switched his focus to prose, and spent the next several years working for literary journals and periodicals, becoming known for his own style of literary criticism. His work forced him to move between several cities, including Baltimore, Philadelphia, and New York City. In 1836, when he was 27, he married his 13-year-old cousin, Virginia Clemm. She died of tuberculosis in 1847. In January 1845, he published his poem "The Raven" to instant success. He planned for years to produce his own journal The Penn, later renamed The Stylus. But before it began publishing, Poe died in Baltimore in 1849, aged 40, under mysterious circumstances. The cause of his death remains unknown, and has been variously attributed to many causes including disease, alcoholism, substance abuse, and suicide.</td>
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900">2024-06-02 14:43:47</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
Ma ora abbiamo un problema con Tailwind: non riprende i nuovi stili CSS che abbiamo aggiunto. Dobbiamo aggiungere la posizione dei componenti Vue al file di configurazione Tailwind, in modo che raccolga e compili automaticamente le classi utilizzate in Vue.
Modifichiamo il file tailwind.config.js:
import defaultTheme from 'tailwindcss/defaultTheme';
import forms from '@tailwindcss/forms';
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
'./resources/js/components/**/*.vue',
],
theme: {
extend: {
fontFamily: {
sans: ['Figtree', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [forms],
};