Příklady použití Asset
Praktické příklady a best practices.
Základní použití v tazích
Asset vrací pole URL (ne HTML string). Renderování zajišťuje přidružená .tpl šablona.
Frontend – Veřejný web
Tag app/website/tags/assets/website.php:
<?php
declare(strict_types=1);
use Core\Asset\Asset;
use Core\Template\Template;
$entryPoint = 'website.js';
$assets = Asset::viteAssets(CONFIG['vite_website'], $entryPoint);
$tpl = new Template();
$tpl->data('assets', $assets);
$tpl->data('nonce', defined('CSP_NONCE') ? CSP_NONCE : '');
echo $tpl->draw(__DIR__ . '/website.tpl');
Přidružená šablona app/website/tags/assets/website.tpl:
{loop="$assets.preload"}
<link rel="modulepreload"{if="$nonce"} nonce="{$nonce}"{/if} href="{$value}">
{/loop}
{loop="$assets.js"}
<script type="module" crossorigin{if="$nonce"} nonce="{$nonce}"{/if} src="{$value}"></script>
{/loop}
{loop="$assets.css"}
<link rel="stylesheet" href="{$value}">
{/loop}
V šabloně stránky:
<!DOCTYPE html>
<html>
<head>
{T assets/website}
</head>
<body>
<!-- obsah -->
</body>
</html>
Dev režim – výstup:
<script type="module" crossorigin src="http://localhost:5174/website.js"></script>
Production – výstup:
<script type="module" crossorigin src="/js/website.js?1705234567"></script>
<link rel="stylesheet" href="/css/frontend.css?1705234567">
Admin Panel – Různé vstupní body
Tag app/admin/tags/assets/admin.php:
<?php
declare(strict_types=1);
use Core\Asset\Asset;
use Core\Template\Template;
$entryPoint = (PAGE === 'login') ? 'login.js' : 'admin.js';
$assets = Asset::viteAssets(CONFIG['vite_admin'], $entryPoint);
$tpl = new Template();
$tpl->data('assets', $assets);
$tpl->data('nonce', defined('CSP_NONCE') ? CSP_NONCE : '');
echo $tpl->draw(__DIR__ . '/admin.tpl');
V PHP kódu (např. Html::wrap()):
$tpl->data('assets', Asset::viteAssets(CONFIG['vite_admin'], 'admin.js'));
Dev režim – admin.js:
<script type="module" crossorigin src="http://localhost:5173/admin.js"></script>
Production – admin.js:
<script type="module" crossorigin src="/ADMIN/js/admin.js?1705234567"></script>
<link rel="stylesheet" href="/ADMIN/css/admin.css?1705234567">
<link rel="stylesheet" href="/ADMIN/css/main.css?1705234568">
Manifest automaticky řeší všechny CSS a JS závislosti.
Dev vs Production workflow
Development
Spuštění dev serveru:
cd src/
bun run dev # Spustí Vite na portu 5173 (admin) a 5174 (website)
V prohlížeči:
- Šablona zavolá tag
{T assets/website} Asset::viteAssets()detekuje běžící server na 5174- Vrátí
['js' => ['http://localhost:5174/website.js'], ...] - Šablona vyrenderuje
<script src="http://localhost:5174/website.js"> - Prohlížeč stáhne JS přímo z dev serveru
- Změna souboru v
/src/frontend/→ HMR aktualizuje prohlížeč
Production
Build:
cd src/
bun run build # Kompiluje do /public/ a /public/ADMIN/
Co se stane:
- Vite optimalizuje/minifikuje JS a CSS
- Vygeneruje bundly
- Vytvoří
.vite/manifest.jsonv/public/a/public/ADMIN/
Manifest obsah:
{
"website.js": {
"file": "js/website.js",
"css": ["css/website.css"],
"imports": ["_shared.js"]
},
"_shared.js": {
"file": "js/shared.js"
}
}
V prohlížeči:
- Šablona zavolá tag
{T assets/website} Asset::viteAssets()nedetekuje dev server- Čte
/public/.vite/manifest.json - Vrátí pole URL s verzemi
- Šablona vyrenderuje optimalizované tagy s cache-bustingem
Příklady vstupních bodů
Admin panel s více vstupními body
/src/backend/admin.js – Hlavní admin:
import './js/main.js';
import './js/init.js';
import './js/tabs.js';
import './scss/main.scss';
/src/backend/login.js – Login stránka:
import './js/login.js';
import './scss/login.scss';
V tagu zvolíš správný vstupní bod:
$entryPoint = (PAGE === 'login') ? 'login.js' : 'admin.js';
$assets = Asset::viteAssets(CONFIG['vite_admin'], $entryPoint);
Frontend s jedním vstupním bodem
/src/frontend/website.js – Kompletní frontend:
import './js/base.js';
import './js/init.js';
import './js/gallery.js';
import './scss/website.scss';
V tagu:
$assets = Asset::viteAssets(CONFIG['vite_website'], 'website.js');
Manifest řešení – Co vidíš v production
Příklad: Login stránka
Manifest:
{
"login.js": {
"file": "js/login.js",
"src": "login.js",
"isEntry": true,
"imports": ["_main.js"],
"css": ["css/login.css"]
},
"_main.js": {
"file": "js/main.js",
"css": ["css/main.css"]
}
}
viteAssets() vrátí:
[
'js' => ['/ADMIN/js/login.js?1705234567', '/ADMIN/js/main.js?1705234568'],
'preload' => [],
'css' => ['/ADMIN/css/login.css?1705234568', '/ADMIN/css/main.css?1705234569'],
]
Šablona vyrenderuje:
<script type="module" crossorigin src="/ADMIN/js/login.js?1705234567"></script>
<script type="module" crossorigin src="/ADMIN/js/main.js?1705234568"></script>
<link rel="stylesheet" href="/ADMIN/css/login.css?1705234568">
<link rel="stylesheet" href="/ADMIN/css/main.css?1705234569">
Co se stalo:
- Najde
login.jsv manifestu - Přidá URL pro hlavní soubor
- Rekurzivně zpracuje
imports→ přidá_main.js - Všechna CSS z obou souborů se přidají
- Deduplikuje (CSS se neopakuje)
Docker prostředí
Asset automaticky detekuje Docker a používá správné hostname:
$host = isPetrovoDockerEnvironment() ? 'host.docker.internal' : 'localhost';
// fsockopen testuje správný host
Best Practices
Správně – Oddělené vstupní body
$entryPoint = (PAGE === 'login') ? 'login.js' : 'admin.js';
$assets = Asset::viteAssets(CONFIG['vite_admin'], $entryPoint);
- Login stránka nezačíná s celým admin JS
- Menší bundle pro login
- Lepší performance
Špatně – Jeden vstupní bod pro všechno
$assets = Asset::viteAssets(CONFIG['vite_admin'], 'admin.js');
// Login stránka stahuje zbytečný admin JS
Správně – Konfigurace v config/
# config/development.yaml
vite_admin: http://localhost:5173
vite_website: http://localhost:5174
Používáno v tazích:
$assets = Asset::viteAssets(CONFIG['vite_admin'], 'admin.js');
Špatně – Hardcoded URLs
$assets = Asset::viteAssets('http://localhost:5173', 'admin.js'); // URL v kódu
Troubleshooting
Dev server nedetekuje
# Zkontroluj zda server běží
cd src/ && bun run dev
# Ruční test
php -r "echo stream_socket_client('tcp://localhost:5173') ? 'OK' : 'FAIL';"
CSS se nenačítá
// Zkontroluj manifest
file_get_contents('/public/.vite/manifest.json');
// CSS musí být v "css" poli vstupního bodu
{
"admin.js": {
"css": ["css/admin.css"] // Mělo by tu být
}
}
Chybí? → Přidej import v src/backend/admin.js:
import './scss/admin.scss';
Verze v URL se nemění
// Verze se bere z filemtime() — soubor musí existovat
// Pokud soubor neexistuje → random číslo (1000-9999)
// Zkontroluj že build proběhl
file_exists('/public/js/admin.js') // ? true : false
// Pokud build failed → zkus znova
cd src/ && bun run build
Performance monitoring
Asset přidává verze v URL:
<script src="/js/admin.js?1705234567"></script>
Query string ?1705234567 je filemtime() souboru:
- Soubor se změní → nová verze → prohlížeč ho znovu stáhne
- Starší verze zůstávají v cache
- Zero cold-start pro statické soubory