Nette Assets

Stanco di gestire manualmente i file statici nelle tue applicazioni web? Dimentica la codifica manuale dei percorsi, la gestione dell'invalidazione della cache o la preoccupazione per il versioning dei file. Nette Assets trasforma il modo in cui lavori con immagini, fogli di stile, script e altre risorse statiche.

  • Versioning intelligente assicura che i browser carichino sempre i file più recenti
  • Rilevamento automatico dei tipi di file e delle dimensioni
  • Integrazione Latte senza soluzione di continuità con tag intuitivi
  • Architettura flessibile che supporta filesystem, CDN e Vite
  • Caricamento pigro (Lazy loading) per prestazioni ottimali

Perché Nette Assets?

Lavorare con i file statici spesso significa codice ripetitivo e soggetto a errori. Costruisci manualmente URL, aggiungi parametri di versione per il cache busting e gestisci diversi tipi di file in modo diverso. Questo porta a codice come:

<img src="/images/logo.png?v=1699123456" width="200" height="100" alt="Logo">
<link rel="stylesheet" href="/css/style.css?v=2">

Con Nette Assets, tutta questa complessità scompare:

{* Tutto automatizzato - URL, versioning, dimensioni *}
<img n:asset="images/logo.png">
<link n:asset="css/style.css">

{* O semplicemente *}
{asset 'css/style.css'}

Questo è tutto! La libreria automaticamente:

  • Aggiunge parametri di versione basati sull'ora di modifica del file
  • Rileva le dimensioni dell'immagine e le include nell'HTML
  • Genera l'elemento HTML corretto per ogni tipo di file
  • Gestisce sia gli ambienti di sviluppo che di produzione

Installazione

Installa Nette Assets usando Composer:

composer require nette/assets

Richiede PHP 8.1 o superiore e funziona perfettamente con Nette Framework, ma può essere usato anche in modo standalone.

Primi Passi

Nette Assets funziona subito senza alcuna configurazione. Posiziona i tuoi file statici nella directory www/assets/ e inizia ad usarli:

{* Visualizza un'immagine con dimensioni automatiche *}
{asset 'logo.png'}

{* Includi un foglio di stile con versioning *}
{asset 'style.css'}

{* Carica un modulo JavaScript *}
{asset 'app.js'}

Per un maggiore controllo sull'HTML generato, usa l'attributo n:asset o la funzione asset().

Come Funziona

Nette Assets è costruito attorno a tre concetti fondamentali che lo rendono potente ma semplice da usare:

Assets – I Tuoi File Resi Intelligenti

Un asset rappresenta qualsiasi file statico nella tua applicazione. Ogni file diventa un oggetto con utili proprietà di sola lettura:

$image = $assets->getAsset('photo.jpg');
echo $image->url;      // '/assets/photo.jpg?v=1699123456'
echo $image->width;    // 1920
echo $image->height;   // 1080
echo $image->mimeType; // 'image/jpeg'

Diversi tipi di file forniscono proprietà diverse:

  • Immagini: larghezza, altezza, testo alternativo, caricamento pigro
  • Script: tipo di modulo, hash di integrità, crossorigin
  • Fogli di stile: media queries, integrità
  • Audio/Video: durata, dimensioni
  • Font: precaricamento corretto con CORS

La libreria rileva automaticamente i tipi di file e crea la classe asset appropriata.

Mappers – Da Dove Vengono i File

Un mapper sa come trovare i file e creare URL per essi. Puoi avere più mapper per scopi diversi – file locali, CDN, cloud storage o strumenti di build (ognuno di essi ha un nome). Il FilesystemMapper integrato gestisce i file locali, mentre ViteMapper si integra con i moderni strumenti di build.

I mapper sono definiti nella Configurazione.

Registry – La Tua Interfaccia Principale

Il registry gestisce tutti i mapper e fornisce l'API principale:

// Inietta il registry nel tuo servizio
public function __construct(
	private Nette\Assets\Registry $assets
) {}

// Ottieni assets da diversi mapper
$logo = $this->assets->getAsset('images:logo.png'); // mapper 'image'
$app = $this->assets->getAsset('app:main.js'); // mapper 'app'
$style = $this->assets->getAsset('style.css'); // usa il mapper predefinito

Il registry seleziona automaticamente il mapper corretto e memorizza i risultati nella cache per le prestazioni.

Lavorare con gli Assets in PHP

Il Registry fornisce due metodi per recuperare gli asset:

// Lancia Nette\Assets\AssetNotFoundException se il file non esiste
$logo = $assets->getAsset('logo.png');

// Restituisce null se il file non esiste
$banner = $assets->tryGetAsset('banner.jpg');
if ($banner) {
	echo $banner->url;
}

Specificare i Mapper

Puoi scegliere esplicitamente quale mapper usare:

// Usa il mapper predefinito
$file = $assets->getAsset('document.pdf');

// Usa un mapper specifico con prefisso
$image = $assets->getAsset('images:photo.jpg');

// Usa un mapper specifico con sintassi array
$script = $assets->getAsset(['scripts', 'app.js']);

Proprietà e Tipi di Asset

Ogni tipo di asset fornisce proprietà di sola lettura rilevanti:

// Proprietà dell'immagine
$image = $assets->getAsset('photo.jpg');
echo $image->width;     // 1920
echo $image->height;    // 1080
echo $image->mimeType;  // 'image/jpeg'

// Proprietà dello script
$script = $assets->getAsset('app.js');
echo $script->type;     // 'module' o null

// Proprietà audio
$audio = $assets->getAsset('song.mp3');
echo $audio->duration;  // durata in secondi

// Tutti gli asset possono essere convertiti in stringa (restituisce URL)
$url = (string) $assets->getAsset('document.pdf');

Le proprietà come le dimensioni o la durata vengono caricate pigramente solo quando vi si accede, mantenendo la libreria veloce.

Uso degli Assets nei Template Latte

Nette Assets fornisce un'integrazione Latte intuitiva con tag e funzioni.

{asset}

Il tag {asset} renderizza elementi HTML completi:

{* Renderizza: <img src="/assets/hero.jpg?v=123" width="1920" height="1080"> *}
{asset 'hero.jpg'}

{* Renderizza: <script src="/assets/app.js?v=456" type="module"></script> *}
{asset 'app.js'}

{* Renderizza: <link rel="stylesheet" href="/assets/style.css?v=789"> *}
{asset 'style.css'}

Il tag automaticamente:

  • Rileva il tipo di asset e genera l'HTML appropriato
  • Include il versioning per il cache busting
  • Aggiunge le dimensioni per le immagini
  • Imposta gli attributi corretti (type, media, ecc.)

Quando usato all'interno di attributi HTML, produce solo l'URL:

<div style="background-image: url({asset 'bg.jpg'})">
<img srcset="{asset 'logo@2x.png'} 2x">

n:asset

Per un controllo completo sugli attributi HTML:

{* L'attributo n:asset riempie src, dimensioni, ecc. *}
<img n:asset="product.jpg" alt="Prodotto" class="rounded">

{* Funziona con qualsiasi elemento rilevante *}
<script n:asset="analytics.js" defer></script>
<link n:asset="print.css" media="print">
<audio n:asset="podcast.mp3" controls></audio>

Usa variabili e mapper:

{* Le variabili funzionano naturalmente *}
<img n:asset="$product->image">

{* Specifica il mapper con le parentesi graffe *}
<img n:asset="images:{$product->image}">

{* Specifica il mapper con la notazione array *}
<img n:asset="[images, $product->image]">

asset()

Per la massima flessibilità, usa la funzione asset():

{var $logo = asset('logo.png')}
<img src={$logo} width={$logo->width} height={$logo->height}>

{* O direttamente *}
<img src={asset('logo.png')} alt="Logo">

Assets Opzionali

Gestisci gli asset mancanti con {asset?}, n:asset? e tryAsset():

{* Tag opzionale - non renderizza nulla se l'asset manca *}
{asset? 'optional-banner.jpg'}

{* Attributo opzionale - salta se l'asset manca *}
<img n:asset?="user-avatar.jpg" alt="Avatar" class="avatar">

{* Con fallback *}
{var $avatar = tryAsset('user-avatar.jpg') ?? asset('default-avatar.jpg')}
<img n:asset=$avatar alt="Avatar">

{preload}

Migliora le prestazioni di caricamento della pagina:

{* Nella tua sezione <head> *}
{preload 'critical.css'}
{preload 'important-font.woff2'}
{preload 'hero-image.jpg'}

Genera i link di precaricamento appropriati:

<link rel="preload" href="/assets/critical.css?v=123" as="style">
<link rel="preload" href="/assets/important-font.woff2" as="font" crossorigin>
<link rel="preload" href="/assets/hero-image.jpg" as="image">

Funzionalità Avanzate

Rilevamento Automatico dell'Estensione

Gestisci automaticamente più formati:

assets:
	mapping:
		images:
			path: img
			extension: [webp, jpg, png]  # Prova in ordine

Ora puoi richiedere senza estensione:

{* Trova logo.webp, logo.jpg, o logo.png automaticamente *}
{asset 'images:logo'}

Perfetto per il progressive enhancement con formati moderni.

Versioning Intelligente

I file vengono automaticamente versionati in base all'ora di modifica:

{asset 'style.css'}
{* Output: <link rel="stylesheet" href="/assets/style.css?v=1699123456"> *}

Quando aggiorni il file, il timestamp cambia, forzando l'aggiornamento della cache del browser.

Controlla il versioning per ogni asset:

// Disabilita il versioning per un asset specifico
$asset = $assets->getAsset('style.css', ['version' => false]);

// In Latte
{asset 'style.css', version: false}

Assets Font

I font ricevono un trattamento speciale con CORS appropriato:

{* Precaricamento corretto con crossorigin *}
{preload 'fonts:OpenSans-Regular.woff2'}

{* Usa in CSS *}
<style>
@font-face {
	font-family: 'Open Sans';
	src: url('{asset 'fonts:OpenSans-Regular.woff2'}') format('woff2');
	font-display: swap;
}
</style>

Mappers Personalizzati

Crea mapper personalizzati per esigenze speciali come l'archiviazione cloud o la generazione dinamica:

use Nette\Assets\Mapper;
use Nette\Assets\Asset;
use Nette\Assets\Helpers;

class CloudStorageMapper implements Mapper
{
	public function __construct(
		private CloudClient $client,
		private string $bucket,
	) {}

	public function getAsset(string $reference, array $options = []): Asset
	{
		if (!$this->client->exists($this->bucket, $reference)) {
			throw new Nette\Assets\AssetNotFoundException("Asset '$reference' not found");
		}

		$url = $this->client->getPublicUrl($this->bucket, $reference);
		return Helpers::createAssetFromUrl($url);
	}
}

Registra nella configurazione:

assets:
	mapping:
		cloud: CloudStorageMapper(@cloudClient, 'my-bucket')

Usa come qualsiasi altro mapper:

{asset 'cloud:user-uploads/photo.jpg'}

Il metodo Helpers::createAssetFromUrl() crea automaticamente il tipo di asset corretto in base all'estensione del file.

Ulteriori letture

versione: 1.0