Integrazione Vite

Le moderne applicazioni JavaScript richiedono strumenti di build sofisticati. Nette Assets fornisce un'integrazione di prima classe con Vite, lo strumento di build frontend di nuova generazione. Ottieni uno sviluppo fulmineo con Hot Module Replacement (HMR) e build di produzione ottimizzate senza problemi di configurazione.

  • Zero configurazione – ponte automatico tra Vite e i template PHP
  • Gestione completa delle dipendenze – un solo tag gestisce tutti gli asset
  • Hot Module Replacement – aggiornamenti istantanei di JavaScript e CSS
  • Build di produzione ottimizzate – code splitting e tree shaking

Nette Assets si integra perfettamente con Vite, così ottieni tutti questi vantaggi mentre scrivi i tuoi template come al solito.

Configurazione di Vite

Configuriamo Vite passo dopo passo. Non preoccuparti se sei nuovo agli strumenti di build – spiegheremo tutto!

Passo 1: Installa Vite

Per prima cosa, installa Vite e il plugin Nette nel tuo progetto:

npm install -D vite @nette/vite-plugin

Questo installa Vite e un plugin speciale che aiuta Vite a funzionare perfettamente con Nette.

Passo 2: Struttura del Progetto

L'approccio standard è quello di posizionare i file sorgente degli asset in una cartella assets/ nella radice del tuo progetto, e le versioni compilate in www/assets/:

web-project/
├── assets/                   ← file sorgente (SCSS, TypeScript, immagini sorgente)
│   ├── public/               ← file statici (copiati così come sono)
│   │   └── favicon.ico
│   ├── images/
│   │   └── logo.png
│   ├── app.js                ← punto di ingresso principale
│   └── style.css             ← i tuoi stili
└── www/                      ← directory pubblica (document root)
	├── assets/               ← i file compilati andranno qui
	└── index.php

La cartella assets/ contiene i tuoi file sorgente – il codice che scrivi. Vite elaborerà questi file e metterà le versioni compilate in www/assets/.

Passo 3: Configura Vite

Crea un file vite.config.ts nella radice del tuo progetto. Questo file dice a Vite dove trovare i tuoi file sorgente e dove mettere quelli compilati.

Il plugin Nette Vite viene fornito con impostazioni predefinite intelligenti che semplificano la configurazione. Presuppone che i tuoi file sorgente front-end si trovino nella directory assets/ (opzione root) e che i file compilati vadano in www/assets/ (opzione outDir). Devi solo specificare il punto di ingresso:

import { defineConfig } from 'vite';
import nette from '@nette/vite-plugin';

export default defineConfig({
	plugins: [
		nette({
			entry: 'app.js',
		}),
	],
});

Se vuoi specificare un altro nome di directory per costruire i tuoi asset, dovrai cambiare alcune opzioni:

export default defineConfig({
	root: 'assets', // directory radice degli asset sorgente

	build: {
		outDir: '../www/assets',  // dove vanno i file compilati
	},

	// ... altra configurazione ...
});

Il percorso outDir è considerato relativo a root, ecco perché c'è ../ all'inizio.

Passo 4: Configura Nette

Dì a Nette Assets di Vite nel tuo common.neon:

assets:
	mapping:
		default:
			type: vite      # dice a Nette di usare il ViteMapper
			path: assets

Passo 5: Aggiungi script

Aggiungi questi script al tuo package.json:

{
	"scripts": {
		"dev": "vite",
		"build": "vite build"
	}
}

Ora puoi:

  • npm run dev – avvia il server di sviluppo con hot reloading
  • npm run build – crea file di produzione ottimizzati

Punti di Ingresso

Un punto di ingresso è il file principale da cui la tua applicazione inizia. Da questo file, importi altri file (CSS, moduli JavaScript, immagini), creando un albero di dipendenze. Vite segue queste importazioni e raggruppa tutto insieme.

Esempio di punto di ingresso assets/app.js:

// Importa stili
import './style.css'

// Importa moduli JavaScript
import netteForms from 'nette-forms';
import naja from 'naja';

// Inizializza la tua applicazione
netteForms.initOnLoad();
naja.initialize();

Nel template puoi inserire un punto di ingresso come segue:

{asset 'app.js'}

Nette Assets genera automaticamente tutti i tag HTML necessari – JavaScript, CSS e qualsiasi altra dipendenza.

Punti di Ingresso Multipli

Applicazioni più grandi spesso necessitano di punti di ingresso separati:

export default defineConfig({
	plugins: [
		nette({
			entry: [
				'app.js',      // pagine pubbliche
				'admin.js',    // pannello di amministrazione
			],
		}),
	],
});

Usali in template diversi:

{* Nelle pagine pubbliche *}
{asset 'app.js'}

{* Nel pannello di amministrazione *}
{asset 'admin.js'}

Importante: File Sorgente vs Compilati

È fondamentale capire che in produzione puoi caricare solo:

  1. Punti di ingresso definiti in entry
  2. File dalla directory assets/public/

Non puoi caricare usando {asset} file arbitrari da assets/ – solo asset a cui si fa riferimento da file JavaScript o CSS. Se il tuo file non è referenziato da nessuna parte non verrà compilato. Se vuoi che Vite sia a conoscenza di altri asset, puoi spostarli nella cartella pubblica.

Si prega di notare che per impostazione predefinita, Vite inlinerà tutti gli asset più piccoli di 4KB, quindi non sarai in grado di fare riferimento a questi file direttamente. (Vedi documentazione di Vite).

{* ✓ Questo funziona - è un punto di ingresso *}
{asset 'app.js'}

{* ✓ Questo funziona - è in assets/public/ *}
{asset 'favicon.ico'}

{* ✗ Questo non funzionerà - file casuale in assets/ *}
{asset 'components/button.js'}

Modalità di Sviluppo

La modalità di sviluppo è completamente opzionale ma offre vantaggi significativi quando abilitata. Il vantaggio principale è l'Hot Module Replacement (HMR) – vedi i cambiamenti istantaneamente senza perdere lo stato dell'applicazione, rendendo l'esperienza di sviluppo molto più fluida e veloce.

Vite è uno strumento di build moderno che rende lo sviluppo incredibilmente veloce. A differenza dei bundler tradizionali, Vite serve il tuo codice direttamente al browser durante lo sviluppo, il che significa avvio istantaneo del server, indipendentemente dalle dimensioni del tuo progetto, e aggiornamenti fulminei.

Avvio del Server di Sviluppo

Avvia il server di sviluppo:

npm run dev

Vedrai:

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose

Mantieni questo terminale aperto durante lo sviluppo.

Il plugin Nette Vite rileva automaticamente quando:

  1. Il server di sviluppo Vite è in esecuzione
  2. La tua applicazione Nette è in modalità debug

Quando entrambe le condizioni sono soddisfatte, Nette Assets carica i file dal server di sviluppo Vite invece che dalla directory compilata:

{asset 'app.js'}
{* In sviluppo: <script src="http://localhost:5173/app.js" type="module"></script> *}
{* In produzione: <script src="/assets/app-4a8f9c7.js" type="module"></script> *}

Nessuna configurazione necessaria – funziona e basta!

Lavorare su Domini Diversi

Se il tuo server di sviluppo è in esecuzione su qualcosa di diverso da localhost (come myapp.local), potresti incontrare problemi di CORS (Cross-Origin Resource Sharing). CORS è una funzionalità di sicurezza nei browser web che blocca le richieste tra domini diversi per impostazione predefinita. Quando la tua applicazione PHP è in esecuzione su myapp.local ma Vite è in esecuzione su localhost:5173, il browser li vede come domini diversi e blocca le richieste.

Hai due opzioni per risolvere questo problema:

Opzione 1: Configura CORS

La soluzione più semplice è consentire le richieste cross-origin dalla tua applicazione PHP:

export default defineConfig({
	// ... altra configurazione ...

	server: {
		cors: {
			origin: 'http://myapp.local',  // l'URL della tua app PHP
		},
	},
});

Opzione 2: Esegui Vite sul tuo dominio

L'altra soluzione è far sì che Vite sia in esecuzione sullo stesso dominio della tua applicazione PHP.

export default defineConfig({
	// ... altra configurazione ...

	server: {
		host: 'myapp.local',  // lo stesso della tua app PHP
	},
});

In realtà, anche in questo caso, è necessario configurare CORS perché il server di sviluppo è in esecuzione sullo stesso hostname ma su una porta diversa. Tuttavia, in questo caso, CORS viene configurato automaticamente dal plugin Nette Vite.

Sviluppo HTTPS

Se sviluppi su HTTPS, hai bisogno di certificati per il tuo server di sviluppo Vite. Il modo più semplice è usare un plugin che genera automaticamente i certificati:

npm install -D vite-plugin-mkcert

Ecco come configurarlo in vite.config.ts:

import mkcert from 'vite-plugin-mkcert';

export default defineConfig({
	// ... altra configurazione ...

	plugins: [
		mkcert(),  // genera automaticamente i certificati e abilita https
		nette(),
	],
});

Nota che se stai usando la configurazione CORS (Opzione 1 da sopra), devi aggiornare l'URL di origine per usare https:// invece di http://.

Build di Produzione

Crea file di produzione ottimizzati:

npm run build

Vite:

  • Minifica tutto il JavaScript e il CSS
  • Divide il codice in chunk ottimali
  • Genera nomi di file con hash per il cache-busting
  • Crea un file manifest per Nette Assets

Esempio di output:

www/assets/
├── app-4f3a2b1c.js       # Il tuo JavaScript principale (minificato)
├── app-7d8e9f2a.css      # CSS estratto (minificato)
├── vendor-8c4b5e6d.js    # Dipendenze condivise
└── .vite/
	└── manifest.json     # Mappatura per Nette Assets

I nomi di file con hash assicurano che i browser carichino sempre la versione più recente.

Cartella Pubblica

I file nella directory assets/public/ vengono copiati nell'output senza elaborazione:

assets/
├── public/
│   ├── favicon.ico
│   ├── robots.txt
│   └── images/
│       └── og-image.jpg
├── app.js
└── style.css

Fai riferimento ad essi normalmente:

{* Questi file vengono copiati così come sono *}
<link rel="icon" href={asset 'favicon.ico'}>
<meta property="og:image" content={asset 'images/og-image.jpg'}>

Per i file pubblici, puoi usare le funzionalità di FilesystemMapper:

assets:
	mapping:
		default:
			type: vite
			path: assets
			extension: [webp, jpg, png]  # Prova prima WebP
			versioning: true             # Aggiungi cache-busting

Nella configurazione vite.config.ts puoi cambiare la cartella pubblica usando l'opzione publicDir.

Importazioni Dinamiche

Vite divide automaticamente il codice per un caricamento ottimale. Le importazioni dinamiche ti consentono di caricare il codice solo quando è effettivamente necessario, riducendo la dimensione iniziale del bundle:

// Carica componenti pesanti su richiesta
button.addEventListener('click', async () => {
	let { Chart } = await import('./components/chart.js')
	new Chart(data)
})

Le importazioni dinamiche creano chunk separati che vengono caricati solo quando necessario. Questo è chiamato “code splitting” ed è una delle funzionalità più potenti di Vite. Quando usi le importazioni dinamiche, Vite crea automaticamente file JavaScript separati per ogni modulo importato dinamicamente.

Il tag {asset 'app.js'} non precarica automaticamente questi chunk dinamici. Questo è un comportamento intenzionale – non vogliamo scaricare codice che potrebbe non essere mai usato. I chunk vengono scaricati solo quando l'importazione dinamica viene eseguita.

Tuttavia, se sai che alcune importazioni dinamiche sono critiche e saranno necessarie a breve, puoi precaricarle:

{* Punto di ingresso principale *}
{asset 'app.js'}

{* Precarica importazioni dinamiche critiche *}
{preload 'components/chart.js'}

Questo dice al browser di scaricare il componente del grafico in background, in modo che sia pronto immediatamente quando necessario.

Supporto TypeScript

TypeScript funziona subito:

// assets/main.ts
interface User {
	name: string
	email: string
}

export function greetUser(user: User): void {
	console.log(`Hello, ${user.name}!`)
}

Fai riferimento ai file TypeScript normalmente:

{asset 'main.ts'}

Per il supporto completo di TypeScript, installalo:

npm install -D typescript

Configurazione Aggiuntiva di Vite

Ecco alcune utili opzioni di configurazione di Vite con spiegazioni dettagliate:

export default defineConfig({
	// Directory radice contenente gli asset sorgente
	root: 'assets',

	// Cartella il cui contenuto viene copiato nella directory di output così com'è
	// Predefinito: 'public' (relativo a 'root')
	publicDir: 'public',

	build: {
		// Dove mettere i file compilati (relativo a 'root')
		outDir: '../www/assets',

		// Svuotare la directory di output prima della build?
		// Utile per rimuovere i vecchi file dalle build precedenti
		emptyOutDir: true,

		// Sottodirectory all'interno di outDir per chunk e asset generati
		// Questo aiuta a organizzare la struttura di output
		assetsDir: 'static',

		rollupOptions: {
			// Punto(i) di ingresso - può essere un singolo file o un array di file
			// Ogni punto di ingresso diventa un bundle separato
			input: [
				'app.js',      // applicazione principale
				'admin.js',    // pannello di amministrazione
			],
		},
	},

	server: {
		// Host a cui associare il server di sviluppo
		// Usa '0.0.0.0' per esporre alla rete
		host: 'localhost',

		// Porta per il server di sviluppo
		port: 5173,

		// Configurazione CORS per richieste cross-origin
		cors: {
			origin: 'http://myapp.local',
		},
	},

	css: {
		// Abilita le source map CSS in sviluppo
		devSourcemap: true,
	},

	plugins: [
		nette(),
	],
});

Questo è tutto! Ora hai un sistema di build moderno integrato con Nette Assets.

versione: 1.0