Nette Assets

Už vás nebaví ručně spravovat statické soubory ve vašich webových aplikacích? Zapomeňte na pevné kódování cest, řešení zneplatnění cache nebo starosti s verzováním souborů. Nette Assets transformuje způsob, jakým pracujete s obrázky, styly, skripty a dalšími statickými zdroji.

  • Chytré verzování zajistí, že prohlížeče vždy načtou nejnovější soubory
  • Automatická detekce typů a rozměrů souborů
  • Bezproblémová integrace s Latte pomocí intuitivních tagů
  • Flexibilní architektura podporující souborové systémy, CDN a Vite
  • Líné načítání pro optimální výkon

Proč Nette Assets?

Práce se statickými soubory často znamená opakující se, chybový kód. Ručně konstruujete URL, přidáváte parametry verzí pro zrušení cache a řešíte různé typy souborů odlišně. To vede ke kódu jako:

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

S Nette Assets veškerá tato složitost mizí:

{* Vše automatizováno - URL, verzování, rozměry *}
<img n:asset="images/logo.png">
<link n:asset="css/style.css">

{* Nebo jen *}
{asset 'css/style.css'}

To je vše! Knihovna automaticky:

  • Přidává parametry verzí na základě času poslední úpravy souboru
  • Detekuje rozměry obrázků a zahrnuje je do HTML
  • Generuje správný HTML element pro každý typ souboru
  • Zpracovává vývojové i produkční prostředí

Instalace

Nainstalujte Nette Assets pomocí Composeru:

composer require nette/assets

Vyžaduje PHP 8.1 nebo vyšší a perfektně funguje s Nette Frameworkem, ale lze jej použít i samostatně.

První kroky

Nette Assets funguje ihned po instalaci bez jakékékoli konfigurace. Umístěte své statické soubory do adresáře www/assets/ a začněte je používat:

{* Zobrazí obrázek s automatickými rozměry *}
{asset 'logo.png'}

{* Zahrne šablonu stylů s verzováním *}
{asset 'style.css'}

{* Načte JavaScript modul *}
{asset 'app.js'}

Pro větší kontrolu nad generovaným HTML použijte atribut n:asset nebo funkci asset().

Jak to funguje

Nette Assets je postaveno na třech základních konceptech, které jej činí výkonným, ale zároveň jednoduchým na použití:

Assets – vaše soubory chytře

Asset představuje jakýkoli statický soubor ve vaší aplikaci. Každý soubor se stává objektem s užitečnými vlastnostmi jen pro čtení:

$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'

Různé typy souborů poskytují různé vlastnosti:

  • Obrázky: šířka, výška, alternativní text, líné načítání
  • Skripty: typ modulu, integrity hashe, crossorigin
  • Styly: media queries, integrity
  • Audio/Video: délka, rozměry
  • Fonty: správné přednačítání s CORS

Knihovna automaticky detekuje typy souborů a vytváří odpovídající třídu assetu.

Mappery – odkud soubory pocházejí

Mapper ví, jak najít soubory a vytvořit pro ně URL. Můžete mít více mapperů pro různé účely – lokální soubory, CDN, cloudové úložiště nebo build nástroje (každý z nich má jméno). Vestavěný FilesystemMapper zpracovává lokální soubory, zatímco ViteMapper se integruje s moderními build nástroji.

Mappery jsou definovány v konfiguraci.

Registry – vaše hlavní rozhraní

Registry spravuje všechny mappery a poskytuje hlavní API:

// Vstříkněte registry do vaší služby
public function __construct(
	private Nette\Assets\Registry $assets
) {}

// Získejte assety z různých mapperů
$logo = $this->assets->getAsset('images:logo.png'); // 'image' mapper
$app = $this->assets->getAsset('app:main.js'); // 'app' mapper
$style = $this->assets->getAsset('style.css'); // používá výchozí mapper

Registry automaticky vybírá správný mapper a kešuje výsledky pro výkon.

Práce s Assets v PHP

Registry poskytuje dvě metody pro získávání assetů:

// Vyvolá Nette\Assets\AssetNotFoundException, pokud soubor neexistuje
$logo = $assets->getAsset('logo.png');

// Vrátí null, pokud soubor neexistuje
$banner = $assets->tryGetAsset('banner.jpg');
if ($banner) {
	echo $banner->url;
}

Určení mapperů

Můžete explicitně zvolit, který mapper použít:

// Použít výchozí mapper
$file = $assets->getAsset('document.pdf');

// Použít konkrétní mapper s prefixem
$image = $assets->getAsset('images:photo.jpg');

// Použít konkrétní mapper se syntaxí pole
$script = $assets->getAsset(['scripts', 'app.js']);

Vlastnosti a typy assetů

Každý typ assetu poskytuje relevantní vlastnosti jen pro čtení:

// Vlastnosti obrázku
$image = $assets->getAsset('photo.jpg');
echo $image->width;     // 1920
echo $image->height;    // 1080
echo $image->mimeType;  // 'image/jpeg'

// Vlastnosti skriptu
$script = $assets->getAsset('app.js');
echo $script->type;     // 'module' or null

// Vlastnosti audia
$audio = $assets->getAsset('song.mp3');
echo $audio->duration;  // délka v sekundách

// Všechny assety lze přetypovat na řetězec (vrací URL)
$url = (string) $assets->getAsset('document.pdf');

Vlastnosti jako rozměry nebo délka se načítají líně pouze při přístupu, což udržuje knihovnu rychlou.

Použití Assets v Latte šablonách

Nette Assets poskytuje intuitivní integraci s Latte pomocí tagů a funkcí.

{asset}

Tag {asset} vykresluje kompletní HTML elementy:

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

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

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

Tag automaticky:

  • Detekuje typ assetu a generuje odpovídající HTML
  • Zahrnuje verzování pro zrušení cache
  • Přidává rozměry pro obrázky
  • Nastavuje správné atributy (typ, media atd.)

Při použití uvnitř HTML atributů vypíše pouze URL:

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

n:asset

Pro plnou kontrolu nad HTML atributy:

{* Atribut n:asset vyplní src, rozměry atd. *}
<img n:asset="product.jpg" alt="Product" class="rounded">

{* Funguje s jakýmkoli relevantním elementem *}
<script n:asset="analytics.js" defer></script>
<link n:asset="print.css" media="print">
<audio n:asset="podcast.mp3" controls></audio>

Použijte proměnné a mappery:

{* Proměnné fungují přirozeně *}
<img n:asset="$product->image">

{* Určete mapper pomocí složených závorek *}
<img n:asset="images:{$product->image}">

{* Určete mapper pomocí zápisu pole *}
<img n:asset="[images, $product->image]">

asset()

Pro maximální flexibilitu použijte funkci asset():

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

{* Nebo přímo *}
<img src={asset('logo.png')} alt="Logo">

Volitelné Assets

Elegantně zpracujte chybějící assety pomocí {asset?}, n:asset? a tryAsset():

{* Volitelný tag – nevykreslí nic, pokud asset chybí *}
{asset? 'optional-banner.jpg'}

{* Volitelný atribut – přeskočí, pokud asset chybí *}
<img n:asset?="user-avatar.jpg" alt="Avatar" class="avatar">

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

{preload}

Zlepšete výkon načítání stránky:

{* Ve vaší sekci <head> *}
{preload 'critical.css'}
{preload 'important-font.woff2'}
{preload 'hero-image.jpg'}

Generuje odpovídající preload odkazy:

<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">

Pokročilé funkce

Automatická detekce přípon

Automaticky zpracovává více formátů:

assets:
	mapping:
		images:
			path: img
			extension: [webp, jpg, png]  # Zkusit v pořadí

Nyní můžete požadovat bez přípony:

{* Automaticky najde logo.webp, logo.jpg nebo logo.png *}
{asset 'images:logo'}

Ideální pro progresivní vylepšení s moderními formáty.

Chytré verzování

Soubory jsou automaticky verzovány na základě času poslední úpravy:

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

Když soubor aktualizujete, časové razítko se změní, což vynutí obnovení cache prohlížeče.

Kontrola verzování pro každý asset:

// Zakázat verzování pro konkrétní asset
$asset = $assets->getAsset('style.css', ['version' => false]);

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

Assety fontů

Fonty získávají speciální zacházení se správným CORS:

{* Správné přednačtení s crossorigin *}
{preload 'fonts:OpenSans-Regular.woff2'}

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

Vlastní mappery

Vytvořte vlastní mappery pro speciální potřeby, jako je cloudové úložiště nebo dynamické generování:

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);
	}
}

Registrace v konfiguraci:

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

Použijte jako jakýkoli jiný mapper:

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

Metoda Helpers::createAssetFromUrl() automaticky vytvoří správný typ assetu na základě přípony souboru.

Další četba

verze: 1.0