Skip to content

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:

  1. Šablona zavolá tag {T assets/website}
  2. Asset::viteAssets() detekuje běžící server na 5174
  3. Vrátí ['js' => ['http://localhost:5174/website.js'], ...]
  4. Šablona vyrenderuje <script src="http://localhost:5174/website.js">
  5. Prohlížeč stáhne JS přímo z dev serveru
  6. 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:

  1. Vite optimalizuje/minifikuje JS a CSS
  2. Vygeneruje bundly
  3. Vytvoří .vite/manifest.json v /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:

  1. Šablona zavolá tag {T assets/website}
  2. Asset::viteAssets() nedetekuje dev server
  3. Čte /public/.vite/manifest.json
  4. Vrátí pole URL s verzemi
  5. Š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:

  1. Najde login.js v manifestu
  2. Přidá URL pro hlavní soubor
  3. Rekurzivně zpracuje imports → přidá _main.js
  4. Všechna CSS z obou souborů se přidají
  5. 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