Nette Documentation Preview

syntax
Nette Assets
************

<div class=perex>

Втомилися вручну керувати статичними файлами у своїх веб-додатках? Забудьте про жорстке кодування шляхів, проблеми з інвалідацією кешу або турботи про версіонування файлів. Nette Assets змінює спосіб роботи з зображеннями, таблицями стилів, скриптами та іншими статичними ресурсами.

- **Розумне версіонування** гарантує, що браузери завжди завантажують найновіші файли
- **Автоматичне визначення** типів файлів та розмірів
- **Безшовна інтеграція Latte** з інтуїтивно зрозумілими тегами
- **Гнучка архітектура**, що підтримує файлові системи, CDN та Vite
- **Ледаче завантаження** для оптимальної продуктивності

</div>


Чому Nette Assets?
==================

Робота зі статичними файлами часто означає повторюваний, схильний до помилок код. Ви вручну створюєте URL-адреси, додаєте параметри версії для обходу кешу та по-різному обробляєте різні типи файлів. Це призводить до такого коду:

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

З Nette Assets вся ця складність зникає:

```latte
{* Everything automated - URL, versioning, dimensions *}
<img n:asset="images/logo.png">
<link n:asset="css/style.css">

{* Or just *}
{asset 'css/style.css'}
```

Ось і все! Бібліотека автоматично:
- Додає параметри версії на основі часу модифікації файлу
- Визначає розміри зображень та включає їх у HTML
- Генерує правильний HTML-елемент для кожного типу файлу
- Обробляє як середовища розробки, так і виробничі середовища


Встановлення
============

Встановіть Nette Assets за допомогою [Composer|best-practices:composer]:

```shell
composer require nette/assets
```

Він вимагає PHP 8.1 або вище та чудово працює з Nette Framework, але також може використовуватися автономно.


Перші кроки
===========

Nette Assets працює "з коробки" без жодної конфігурації. Розмістіть свої статичні файли в каталозі `www/assets/` і почніть їх використовувати:

```latte
{* Display an image with automatic dimensions *}
{asset 'logo.png'}

{* Include a stylesheet with versioning *}
{asset 'style.css'}

{* Load a JavaScript module *}
{asset 'app.js'}
```

Для більшого контролю над згенерованим HTML використовуйте атрибут `n:asset` або функцію `asset()`.


Як це працює
============

Nette Assets побудовано навколо трьох основних концепцій, які роблять його потужним, але простим у використанні:


Активи – Ваші файли стали розумними
-----------------------------------

**Актив** представляє будь-який статичний файл у вашому додатку. Кожен файл стає об'єктом з корисними властивостями тільки для читання:

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

Різні типи файлів надають різні властивості:
- **Зображення**: ширина, висота, альтернативний текст, ледаче завантаження
- **Скрипти**: тип модуля, хеші цілісності, crossorigin
- **Таблиці стилів**: медіа-запити, цілісність
- **Аудіо/Відео**: тривалість, розміри
- **Шрифти**: правильне попереднє завантаження з CORS

Бібліотека автоматично визначає типи файлів та створює відповідний клас активу.


Мапери – Звідки беруться файли
------------------------------

**Мапер** знає, як знаходити файли та створювати для них URL-адреси. Ви можете мати кілька маперів для різних цілей – локальні файли, CDN, хмарне сховище або інструменти збірки (кожен з них має назву). Вбудований `FilesystemMapper` обробляє локальні файли, тоді як `ViteMapper` інтегрується з сучасними інструментами збірки.

Мапери визначаються в [конфігурації |Configuration].


Реєстр – Ваш основний інтерфейс
-------------------------------

**Реєстр** керує всіма маперами та надає основний API:

```php
// Inject the registry in your service
public function __construct(
	private Nette\Assets\Registry $assets
) {}

// Get assets from different mappers
$logo = $this->assets->getAsset('images:logo.png'); // 'image' mapper
$app = $this->assets->getAsset('app:main.js'); // 'app' mapper
$style = $this->assets->getAsset('style.css'); // uses default mapper
```

Реєстр автоматично вибирає правильний мапер та кешує результати для підвищення продуктивності.


Робота з активами в PHP
=======================

Реєстр надає два методи для отримання активів:

```php
// Throws Nette\Assets\AssetNotFoundException if file doesn't exist
$logo = $assets->getAsset('logo.png');

// Returns null if file doesn't exist
$banner = $assets->tryGetAsset('banner.jpg');
if ($banner) {
	echo $banner->url;
}
```


Зазначення маперів
------------------

Ви можете явно вибрати, який мапер використовувати:

```php
// Use default mapper
$file = $assets->getAsset('document.pdf');

// Use specific mapper with prefix
$image = $assets->getAsset('images:photo.jpg');

// Use specific mapper with array syntax
$script = $assets->getAsset(['scripts', 'app.js']);
```


Властивості та типи активів
---------------------------

Кожен тип активу надає відповідні властивості тільки для читання:

```php
// Image properties
$image = $assets->getAsset('photo.jpg');
echo $image->width;     // 1920
echo $image->height;    // 1080
echo $image->mimeType;  // 'image/jpeg'

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

// Audio properties
$audio = $assets->getAsset('song.mp3');
echo $audio->duration;  // duration in seconds

// All assets can be cast to string (returns URL)
$url = (string) $assets->getAsset('document.pdf');
```

.[note]
Властивості, такі як розміри або тривалість, завантажуються ледаче лише при доступі, що забезпечує швидку роботу бібліотеки.


Використання активів у шаблонах Latte
=====================================

Nette Assets надає інтуїтивно зрозумілу інтеграцію [Latte|latte:] з тегами та функціями.


`{asset}`
---------

Тег `{asset}` рендерить повні HTML-елементи:

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

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

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

Тег автоматично:
- Визначає тип активу та генерує відповідний HTML
- Включає версіонування для обходу кешу
- Додає розміри для зображень
- Встановлює правильні атрибути (type, media тощо)

При використанні всередині HTML-атрибутів він виводить лише URL-адресу:

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


`n:asset`
---------

Для повного контролю над HTML-атрибутами:

```latte
{* The n:asset attribute fills in src, dimensions, etc. *}
<img n:asset="product.jpg" alt="Product" class="rounded">

{* Works with any relevant element *}
<script n:asset="analytics.js" defer></script>
<link n:asset="print.css" media="print">
<audio n:asset="podcast.mp3" controls></audio>
```

Використовуйте змінні та мапери:

```latte
{* Variables work naturally *}
<img n:asset="$product->image">

{* Specify mapper with curly brackets *}
<img n:asset="images:{$product->image}">

{* Specify mapper with array notation *}
<img n:asset="[images, $product->image]">
```


`asset()`
---------

Для максимальної гнучкості використовуйте функцію `asset()`:

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

{* Or directly *}
<img src={asset('logo.png')} alt="Logo">
```


Необов'язкові активи
--------------------

Обробляйте відсутні активи елегантно за допомогою `{asset?}`, `n:asset?` та `tryAsset()`:

```latte
{* Optional tag - renders nothing if asset missing *}
{asset? 'optional-banner.jpg'}

{* Optional attribute - skips if asset missing *}
<img n:asset?="user-avatar.jpg" alt="Avatar" class="avatar">

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


`{preload}`
-----------

Покращити продуктивність завантаження сторінки:

```latte
{* In your <head> section *}
{preload 'critical.css'}
{preload 'important-font.woff2'}
{preload 'hero-image.jpg'}
```

Генерує відповідні посилання для попереднього завантаження:

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


Розширені можливості
====================


Автоматичне визначення розширень
--------------------------------

Автоматично обробляти кілька форматів:

```neon
assets:
	mapping:
		images:
			path: img
			extension: [webp, jpg, png]  # Try in order
```

Тепер ви можете запитувати без розширення:

```latte
{* Finds logo.webp, logo.jpg, or logo.png automatically *}
{asset 'images:logo'}
```

Ідеально підходить для прогресивного покращення з сучасними форматами.


Розумне версіонування
---------------------

Файли автоматично версіонуються на основі часу модифікації:

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

Коли ви оновлюєте файл, мітка часу змінюється, що примушує браузер оновити кеш.

Контролювати версіонування для кожного активу:

```php
// Disable versioning for specific asset
$asset = $assets->getAsset('style.css', ['version' => false]);

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


Активи шрифтів
--------------

Шрифти отримують особливу обробку з правильним CORS:

```latte
{* Proper preload with crossorigin *}
{preload 'fonts:OpenSans-Regular.woff2'}

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


Користувацькі мапери
====================

Створюйте користувацькі мапери для особливих потреб, таких як хмарне сховище або динамічна генерація:

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

Зареєструвати в конфігурації:

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

Використовувати як будь-який інший мапер:

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

Метод `Helpers::createAssetFromUrl()` автоматично створює правильний тип активу на основі розширення файлу.


Читати далі .[#toc-further-reading]
===================================

- [Nette Assets: Нарешті уніфікований API для всього, від зображень до Vite |https://blog.nette.org/en/introducing-nette-assets]

Nette Assets

Втомилися вручну керувати статичними файлами у своїх веб-додатках? Забудьте про жорстке кодування шляхів, проблеми з інвалідацією кешу або турботи про версіонування файлів. Nette Assets змінює спосіб роботи з зображеннями, таблицями стилів, скриптами та іншими статичними ресурсами.

  • Розумне версіонування гарантує, що браузери завжди завантажують найновіші файли
  • Автоматичне визначення типів файлів та розмірів
  • Безшовна інтеграція Latte з інтуїтивно зрозумілими тегами
  • Гнучка архітектура, що підтримує файлові системи, CDN та Vite
  • Ледаче завантаження для оптимальної продуктивності

Чому Nette Assets?

Робота зі статичними файлами часто означає повторюваний, схильний до помилок код. Ви вручну створюєте URL-адреси, додаєте параметри версії для обходу кешу та по-різному обробляєте різні типи файлів. Це призводить до такого коду:

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

З Nette Assets вся ця складність зникає:

{* Everything automated - URL, versioning, dimensions *}
<img n:asset="images/logo.png">
<link n:asset="css/style.css">

{* Or just *}
{asset 'css/style.css'}

Ось і все! Бібліотека автоматично:

  • Додає параметри версії на основі часу модифікації файлу
  • Визначає розміри зображень та включає їх у HTML
  • Генерує правильний HTML-елемент для кожного типу файлу
  • Обробляє як середовища розробки, так і виробничі середовища

Встановлення

Встановіть Nette Assets за допомогою Composer:

composer require nette/assets

Він вимагає PHP 8.1 або вище та чудово працює з Nette Framework, але також може використовуватися автономно.

Перші кроки

Nette Assets працює „з коробки“ без жодної конфігурації. Розмістіть свої статичні файли в каталозі www/assets/ і почніть їх використовувати:

{* Display an image with automatic dimensions *}
{asset 'logo.png'}

{* Include a stylesheet with versioning *}
{asset 'style.css'}

{* Load a JavaScript module *}
{asset 'app.js'}

Для більшого контролю над згенерованим HTML використовуйте атрибут n:asset або функцію asset().

Як це працює

Nette Assets побудовано навколо трьох основних концепцій, які роблять його потужним, але простим у використанні:

Активи – Ваші файли стали розумними

Актив представляє будь-який статичний файл у вашому додатку. Кожен файл стає об'єктом з корисними властивостями тільки для читання:

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

Різні типи файлів надають різні властивості:

  • Зображення: ширина, висота, альтернативний текст, ледаче завантаження
  • Скрипти: тип модуля, хеші цілісності, crossorigin
  • Таблиці стилів: медіа-запити, цілісність
  • Аудіо/Відео: тривалість, розміри
  • Шрифти: правильне попереднє завантаження з CORS

Бібліотека автоматично визначає типи файлів та створює відповідний клас активу.

Мапери – Звідки беруться файли

Мапер знає, як знаходити файли та створювати для них URL-адреси. Ви можете мати кілька маперів для різних цілей – локальні файли, CDN, хмарне сховище або інструменти збірки (кожен з них має назву). Вбудований FilesystemMapper обробляє локальні файли, тоді як ViteMapper інтегрується з сучасними інструментами збірки.

Мапери визначаються в конфігурації.

Реєстр – Ваш основний інтерфейс

Реєстр керує всіма маперами та надає основний API:

// Inject the registry in your service
public function __construct(
	private Nette\Assets\Registry $assets
) {}

// Get assets from different mappers
$logo = $this->assets->getAsset('images:logo.png'); // 'image' mapper
$app = $this->assets->getAsset('app:main.js'); // 'app' mapper
$style = $this->assets->getAsset('style.css'); // uses default mapper

Реєстр автоматично вибирає правильний мапер та кешує результати для підвищення продуктивності.

Робота з активами в PHP

Реєстр надає два методи для отримання активів:

// Throws Nette\Assets\AssetNotFoundException if file doesn't exist
$logo = $assets->getAsset('logo.png');

// Returns null if file doesn't exist
$banner = $assets->tryGetAsset('banner.jpg');
if ($banner) {
	echo $banner->url;
}

Зазначення маперів

Ви можете явно вибрати, який мапер використовувати:

// Use default mapper
$file = $assets->getAsset('document.pdf');

// Use specific mapper with prefix
$image = $assets->getAsset('images:photo.jpg');

// Use specific mapper with array syntax
$script = $assets->getAsset(['scripts', 'app.js']);

Властивості та типи активів

Кожен тип активу надає відповідні властивості тільки для читання:

// Image properties
$image = $assets->getAsset('photo.jpg');
echo $image->width;     // 1920
echo $image->height;    // 1080
echo $image->mimeType;  // 'image/jpeg'

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

// Audio properties
$audio = $assets->getAsset('song.mp3');
echo $audio->duration;  // duration in seconds

// All assets can be cast to string (returns URL)
$url = (string) $assets->getAsset('document.pdf');

Властивості, такі як розміри або тривалість, завантажуються ледаче лише при доступі, що забезпечує швидку роботу бібліотеки.

Використання активів у шаблонах Latte

Nette Assets надає інтуїтивно зрозумілу інтеграцію Latte з тегами та функціями.

{asset}

Тег {asset} рендерить повні HTML-елементи:

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

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

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

Тег автоматично:

  • Визначає тип активу та генерує відповідний HTML
  • Включає версіонування для обходу кешу
  • Додає розміри для зображень
  • Встановлює правильні атрибути (type, media тощо)

При використанні всередині HTML-атрибутів він виводить лише URL-адресу:

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

n:asset

Для повного контролю над HTML-атрибутами:

{* The n:asset attribute fills in src, dimensions, etc. *}
<img n:asset="product.jpg" alt="Product" class="rounded">

{* Works with any relevant element *}
<script n:asset="analytics.js" defer></script>
<link n:asset="print.css" media="print">
<audio n:asset="podcast.mp3" controls></audio>

Використовуйте змінні та мапери:

{* Variables work naturally *}
<img n:asset="$product->image">

{* Specify mapper with curly brackets *}
<img n:asset="images:{$product->image}">

{* Specify mapper with array notation *}
<img n:asset="[images, $product->image]">

asset()

Для максимальної гнучкості використовуйте функцію asset():

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

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

Необов'язкові активи

Обробляйте відсутні активи елегантно за допомогою {asset?}, n:asset? та tryAsset():

{* Optional tag - renders nothing if asset missing *}
{asset? 'optional-banner.jpg'}

{* Optional attribute - skips if asset missing *}
<img n:asset?="user-avatar.jpg" alt="Avatar" class="avatar">

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

{preload}

Покращити продуктивність завантаження сторінки:

{* In your <head> section *}
{preload 'critical.css'}
{preload 'important-font.woff2'}
{preload 'hero-image.jpg'}

Генерує відповідні посилання для попереднього завантаження:

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

Розширені можливості

Автоматичне визначення розширень

Автоматично обробляти кілька форматів:

assets:
	mapping:
		images:
			path: img
			extension: [webp, jpg, png]  # Try in order

Тепер ви можете запитувати без розширення:

{* Finds logo.webp, logo.jpg, or logo.png automatically *}
{asset 'images:logo'}

Ідеально підходить для прогресивного покращення з сучасними форматами.

Розумне версіонування

Файли автоматично версіонуються на основі часу модифікації:

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

Коли ви оновлюєте файл, мітка часу змінюється, що примушує браузер оновити кеш.

Контролювати версіонування для кожного активу:

// Disable versioning for specific asset
$asset = $assets->getAsset('style.css', ['version' => false]);

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

Активи шрифтів

Шрифти отримують особливу обробку з правильним CORS:

{* Proper preload with crossorigin *}
{preload 'fonts:OpenSans-Regular.woff2'}

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

Користувацькі мапери

Створюйте користувацькі мапери для особливих потреб, таких як хмарне сховище або динамічна генерація:

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

Зареєструвати в конфігурації:

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

Використовувати як будь-який інший мапер:

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

Метод Helpers::createAssetFromUrl() автоматично створює правильний тип активу на основі розширення файлу.

Читати далі