Integrace s Vite
Moderní JavaScriptové aplikace vyžadují sofistikované build nástroje. Nette Assets poskytuje prvotřídní integraci s Vite, nástrojem pro frontend build nové generace. Získejte bleskově rychlý vývoj s Hot Module Replacement (HMR) a optimalizované produkční buildy bez potíží s konfigurací.
- Nulová konfigurace – automatické propojení mezi Vite a PHP šablonami
- Kompletní správa závislostí – jeden tag zpracovává všechny assety
- Hot Module Replacement – okamžité aktualizace JavaScriptu a CSS
- Optimalizované produkční buildy – code splitting a tree shaking
Nette Assets se bezproblémově integruje s Vite, takže získáte všechny tyto výhody, zatímco budete psát své šablony jako obvykle.
Nastavení Vite
Pojďme nastavit Vite krok za krokem. Nebojte se, pokud jste v build nástrojích noví – vše vysvětlíme!
Krok 1: Instalace Vite
Nejprve nainstalujte Vite a Nette plugin do vašeho projektu:
npm install -D vite @nette/vite-plugin
Tím se nainstaluje Vite a speciální plugin, který pomáhá Vite perfektně fungovat s Nette.
Krok 2: Struktura projektu
Standardní přístup je umístit zdrojové soubory assetů do složky assets/ v kořenovém adresáři projektu
a zkompilované verze do www/assets/:
web-project/ ├── assets/ ← zdrojové soubory (SCSS, TypeScript, zdrojové obrázky) │ ├── public/ ← statické soubory (kopírovány tak, jak jsou) │ │ └── favicon.ico │ ├── images/ │ │ └── logo.png │ ├── app.js ← hlavní vstupní bod │ └── style.css ← vaše styly └── www/ ← veřejný adresář (document root) ├── assets/ ← zde budou zkompilované soubory └── index.php
Složka assets/ obsahuje vaše zdrojové soubory – kód, který píšete. Vite tyto soubory zpracuje a umístí
zkompilované verze do www/assets/.
Krok 3: Konfigurace Vite
Vytvořte soubor vite.config.ts v kořenovém adresáři projektu. Tento soubor říká Vite, kde má najít
vaše zdrojové soubory a kam má umístit zkompilované.
Nette Vite plugin přichází s chytrými výchozími nastaveními, která zjednodušují konfiguraci. Předpokládá, že
vaše front-end zdrojové soubory jsou v adresáři assets/ (možnost root) a zkompilované soubory
jdou do www/assets/ (možnost outDir). Potřebujete pouze specifikovat vstupní bod:
import { defineConfig } from 'vite';
import nette from '@nette/vite-plugin';
export default defineConfig({
plugins: [
nette({
entry: 'app.js',
}),
],
});
Plugin pod kapotou kromě root a outDir nastavuje ještě několik dalších voleb Vite, aby vše do
sebe zapadlo: base na '' (assety se servírují přímo z document rootu), build.manifest
na true (aby Nette Assets uměly namapovat hashované názvy souborů) a build.assetsDir na
'' (zkompilované soubory jdou přímo do outDir, bez podsložky static/). Kteroukoli
z nich můžete přepsat.
Výchozí outDir (www/assets) vyžaduje, aby adresář www/ už existoval.
Pokud neexistuje, plugin skončí chybou „The output directory … does not exist“.
Pokud chcete zadat jiný název adresáře pro sestavení vašich assetů, budete muset změnit několik možností:
export default defineConfig({
root: 'assets', // kořenový adresář zdrojových assetů
build: {
outDir: '../www/assets', // kam jdou zkompilované soubory
},
// ... další konfigurace ...
});
Cesta outDir je považována za relativní k root, proto je na začátku
../.
Krok 4: Konfigurace Nette
Řekněte Nette Assets o Vite ve vašem common.neon:
assets:
mapping:
default:
type: vite # říká Nette, aby použilo ViteMapper
path: assets
Krok 5: Přidání skriptů
Přidejte tyto skripty do vašeho package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
Nyní můžete:
npm run dev– spustí vývojový server s hot reloadingemnpm run build– vytvoří optimalizované produkční soubory
Vstupní body
Vstupní bod je hlavní soubor, kde začíná vaše aplikace. Z tohoto souboru importujete další soubory (CSS, JavaScript moduly, obrázky), čímž vytváříte strom závislostí. Vite sleduje tyto importy a vše zabalí dohromady.
Příklad vstupního bodu assets/app.js:
// Importovat styly
import './style.css'
// Importovat JavaScript moduly
import netteForms from 'nette-forms';
import naja from 'naja';
// Inicializovat vaši aplikaci
netteForms.initOnLoad();
naja.initialize();
V šabloně můžete vložit vstupní bod následovně:
{asset 'app.js'}
Nette Assets automaticky generuje všechny potřebné HTML tagy – JavaScript, CSS a jakékoli další závislosti.
Více vstupních bodů
Větší aplikace často potřebují samostatné vstupní body:
export default defineConfig({
plugins: [
nette({
entry: [
'app.js', // veřejné stránky
'admin.js', // administrační panel
],
}),
],
});
Použijte je v různých šablonách:
{* Na veřejných stránkách *}
{asset 'app.js'}
{* V administračním panelu *}
{asset 'admin.js'}
Důležité: Zdrojové vs. zkompilované soubory
Je klíčové pochopit, že v produkci můžete načíst pouze soubory, které Vite zpřístupní – buď přes svůj manifest, nebo tím, že je beze změny zkopíruje z veřejné složky:
- Vstupní body definované v
entry(včetně modulů, které dynamicky importují) a assety odkazované z JavaScriptu nebo CSS (obrázky, fonty, …) – to vše je zaznamenáno v manifestu - Soubory z adresáře
assets/public/– ty v manifestu nejsou; kopírují se beze změny a{asset}je najde filesystémovým fallbackem
Nemůžete načítat pomocí {asset} libovolné soubory z assets/ – pokud soubor není nikde
odkazován, nebude zkompilován. Pokud chcete, aby Vite věděl o dalších assetech, můžete je přesunout do veřejné složky.
Vezměte prosím na vědomí, že Vite ve výchozím nastavení vloží všechny assety menší než 4KB, takže tyto soubory nebudete moci přímo odkazovat. (Viz dokumentace Vite).
{* ✓ Toto funguje – je to vstupní bod *}
{asset 'app.js'}
{* ✓ Toto funguje – je to v assets/public/ *}
{asset 'favicon.ico'}
{* ✗ Toto nebude fungovat – náhodný soubor v assets/ *}
{asset 'components/button.js'}
Vývojový režim
Vývojový režim je zcela volitelný, ale po aktivaci poskytuje značné výhody. Hlavní výhodou je Hot Module Replacement (HMR) – okamžitě vidíte změny bez ztráty stavu aplikace, což činí vývoj mnohem plynulejším a rychlejším.
Vite je moderní build nástroj, který činí vývoj neuvěřitelně rychlým. Na rozdíl od tradičních bundlerů Vite během vývoje posílá váš kód přímo do prohlížeče, což znamená okamžitý start serveru bez ohledu na velikost vašeho projektu a bleskově rychlé aktualizace.
Spuštění vývojového serveru
Spusťte vývojový server:
npm run dev
Uvidíte:
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Nechte tento terminál otevřený během vývoje.
Dokud dev server běží, plugin zapisuje malý signální soubor www/assets/.vite/nette.json s jeho URL. Nette
Assets na straně PHP tento soubor čtou a přepnou na načítání z dev serveru, když jsou splněny obě podmínky:
- Vite dev server běží (signální soubor existuje), a
- vaše Nette aplikace je v debug režimu.
Výsledek:
{asset 'app.js'}
{* Ve vývoji: <script src="http://localhost:5173/@vite/client" type="module"></script>
<script src="http://localhost:5173/app.js" type="module"></script> *}
{* V produkci: <script src="/assets/app-4f3a2b1c.js" type="module" crossorigin></script> *}
Není potřeba žádná konfigurace – prostě to funguje! Pokud chcete detekci vypnout nebo zadat URL dev serveru ručně, podívejte se na volbu devServer.
Signální soubor je uložen v www/assets/.vite/nette.json (hned vedle produkčního
manifest.json). Přejmenovat ho můžete volbou pluginu infoFile, která má výchozí hodnotu
.vite/nette.json. Pokud Nette běžící dev server nezachytí, zkontrolujte, že tento soubor existuje a odkazuje na
správnou URL.
Práce na různých doménách
Pokud váš vývojový server běží na něčem jiném než localhost (například myapp.local),
můžete narazit na problémy s CORS (Cross-Origin Resource Sharing). CORS je bezpečnostní funkce ve webových
prohlížečích, která ve výchozím nastavení blokuje požadavky mezi různými doménami. Když vaše PHP aplikace běží na
myapp.local, ale Vite běží na localhost:5173, prohlížeč je vnímá jako různé domény a blokuje
požadavky.
Máte dvě možnosti, jak to vyřešit:
Možnost 1: Konfigurace CORS
Nejjednodušší řešení je povolit cross-origin požadavky z vaší PHP aplikace:
export default defineConfig({
// ... další konfigurace ...
server: {
cors: {
origin: 'http://myapp.local', // URL vaší PHP aplikace
},
},
});
Možnost 2: Spusťte Vite na vaší doméně
Dalším řešením je nechat Vite běžet na stejné doméně jako vaše PHP aplikace.
export default defineConfig({
// ... další konfigurace ...
server: {
host: 'myapp.local', // stejné jako vaše PHP aplikace
},
});
Ve skutečnosti i v tomto případě musíte nakonfigurovat CORS, protože dev server běží na stejném hostiteli, ale na jiném portu. V tomto případě je však CORS automaticky konfigurován Nette Vite pluginem.
Vývoj s HTTPS
Pokud vyvíjíte na HTTPS, potřebujete certifikáty pro váš Vite vývojový server. Nejjednodušší způsob je použití pluginu, který automaticky generuje certifikáty:
npm install -D vite-plugin-mkcert
Zde je, jak to nakonfigurovat v vite.config.ts:
import mkcert from 'vite-plugin-mkcert';
export default defineConfig({
// ... další konfigurace ...
plugins: [
mkcert(), // automaticky generuje certifikáty a povolí https
nette(),
],
});
Všimněte si, že pokud používáte konfiguraci CORS (možnost 1 výše), musíte aktualizovat URL původu tak, aby
používala https:// namísto http://.
Vývoj s Dockerem
Když spouštíte Vite uvnitř Docker kontejneru, je potřeba ohlídat dvě věci: prohlížeč na vašem počítači musí být schopen dosáhnout na vývojový server a Vite musí rozpoznat změny souborů přes hranici kontejneru.
Nejprve z kontejneru zpřístupněte port Vite a navažte vývojový server na všechna rozhraní, aby byl dostupný zvenčí kontejneru:
export default defineConfig({
// ... další konfigurace ...
plugins: [
nette(),
],
server: {
host: '0.0.0.0', // naslouchá na všech rozhraních (v kontejneru nutné)
port: 5173, // musí odpovídat zpřístupněnému portu
strictPort: true, // raději selže, než by zvolil jiný port
watch: {
usePolling: true, // zapněte, pokud se změny souborů na připojených svazcích nedetekují
},
},
});
Plugin zapíše URL vývojového serveru do nette.json pro PHP stranu. Protože host: '0.0.0.0' není
použitelný v prohlížeči (u každého assetu přesměruje na localhost), plugin ho v této URL automaticky
přepíše na localhost, takže se assety načtou správně.
Pokud aplikaci otevíráte na vlastní doméně místo localhost, nastavte host option pluginu na
tuto doménu:
plugins: [
nette({ host: 'myapp.local' }), // stejná doména jako vaše PHP aplikace
],
Plugin pak tento host použije pro URL vývojového serveru, přidá ho mezi CORS origins a povolí ho ve Vite
allowedHosts – takže to funguje bez ruční konfigurace CORS.
U složitějších nasazení – například když Vite běží za reverzní proxy, kde se veřejný host, port i protokol
liší od interní adresy – nastavte ve Vite server.origin na úplnou veřejnou URL. Plugin ji respektuje a
zapíše do nette.json tak, jak je, místo aby URL odvozoval z lokálního socketu:
server: {
origin: 'https://myapp.local:8443', // veřejná URL, na které prohlížeč dosáhne na Vite
},
Produkční buildy
Vytvořte optimalizované produkční soubory:
npm run build
Vite bude:
- Minifikovat veškerý JavaScript a CSS
- Rozdělit kód do optimálních chunků
- Generovat hashované názvy souborů pro cache-busting
- Vytvořit soubor manifestu pro Nette Assets
Příklad výstupu:
www/assets/
├── app-4f3a2b1c.js # Váš hlavní JavaScript (minifikovaný)
├── app-7d8e9f2a.css # Extrahované CSS (minifikované)
├── vendor-8c4b5e6d.js # Sdílené závislosti
└── .vite/
└── manifest.json # Mapování pro Nette Assets
Hashované názvy souborů zajišťují, že prohlížeče vždy načtou nejnovější verzi.
Veřejná složka
Soubory v adresáři assets/public/ jsou kopírovány do výstupu bez zpracování:
assets/
├── public/
│ ├── favicon.ico
│ ├── robots.txt
│ └── images/
│ └── og-image.jpg
├── app.js
└── style.css
Odkazujte na ně normálně:
{* Tyto soubory jsou kopírovány tak, jak jsou *}
<link rel="icon" href={asset 'favicon.ico'}>
<meta property="og:image" content={asset 'images/og-image.jpg'}>
Pro veřejné soubory můžete použít funkce FilesystemMapperu. Volba extension se uplatní u referencí bez
přípony (např. {asset 'images/og-image'} najde nejdřív og-image.webp):
assets:
mapping:
default:
type: vite
path: assets
extension: [webp, jpg, png] # pro reference bez přípony
versioning: true # Přidat cache-busting
V konfiguraci vite.config.ts můžete změnit veřejnou složku pomocí možnosti publicDir.
Dynamické importy
Vite automaticky rozděluje kód pro optimální načítání. Dynamické importy vám umožňují načítat kód pouze tehdy, když je skutečně potřeba, čímž se snižuje počáteční velikost balíčku:
// Načíst náročné komponenty na vyžádání
button.addEventListener('click', async () => {
let { Chart } = await import('./components/chart.js')
new Chart(data)
})
Dynamické importy vytvářejí samostatné chunky, které se načítají pouze v případě potřeby. Tomu se říká „code splitting“ a je to jedna z nejvýkonnějších funkcí Vite. Když používáte dynamické importy, Vite automaticky vytváří samostatné JavaScriptové soubory pro každý dynamicky importovaný modul.
Tag {asset 'app.js'} automaticky nepřednačítá tyto dynamické chunky. Toto je záměrné chování –
nechceme stahovat kód, který by se nikdy nemusel použít. Chunky se stahují pouze při provedení dynamického importu.
Pokud však víte, že určité dynamické importy jsou kritické a budou brzy potřeba, můžete je přednačíst:
{* Hlavní vstupní bod *}
{asset 'app.js'}
{* Přednačíst kritické dynamické importy *}
{preload 'components/chart.js'}
To říká prohlížeči, aby stáhl komponentu grafu na pozadí, takže je okamžitě připravena, když je potřeba.
Podpora TypeScriptu
TypeScript funguje bez další konfigurace:
// assets/main.ts
interface User {
name: string
email: string
}
export function greetUser(user: User): void {
console.log(`Hello, ${user.name}!`)
}
Odkazujte na soubory TypeScriptu normálně (jako u každého souboru musí být main.ts vstupním bodem):
{asset 'main.ts'}
Pro plnou podporu TypeScriptu jej nainstalujte:
npm install -D typescript
Další konfigurace Vite
Zde jsou některé užitečné konfigurační možnosti Vite s podrobnými vysvětleními:
export default defineConfig({
// Kořenový adresář obsahující zdrojové assety
root: 'assets',
// Složka, jejíž obsah je kopírován do výstupního adresáře tak, jak je
// Výchozí: 'public' (relativně k 'root')
publicDir: 'public',
build: {
// Kam umístit zkompilované soubory (relativně k 'root')
outDir: '../www/assets',
// Vyprázdnit výstupní adresář před sestavením?
// Užitečné pro odstranění starých souborů z předchozích buildů
emptyOutDir: true,
// Podadresář uvnitř outDir pro generované chunky a assety
// To pomáhá organizovat výstupní strukturu
assetsDir: 'static',
rollupOptions: {
// Vstupní bod(y) – může být jeden soubor nebo pole souborů
// Každý vstupní bod se stane samostatným balíčkem
input: [
'app.js', // hlavní aplikace
'admin.js', // administrační panel
],
},
},
server: {
// Hostitel, na který se má dev server navázat
// Použijte '0.0.0.0' pro vystavení do sítě
host: 'localhost',
// Port pro dev server
port: 5173,
// Konfigurace CORS pro cross-origin požadavky
cors: {
origin: 'http://myapp.local',
},
},
css: {
// Povolit CSS source mapy ve vývoji
devSourcemap: true,
},
plugins: [
nette(),
],
});
Pozor na cesty ke vstupním bodům v rollupOptions.input výše: Rollup resolvuje relativní cesty
vůči aktuálnímu pracovnímu adresáři (kořeni projektu), ne vůči root: 'assets'. Holé
'app.js' proto při buildu neexistuje. Buď použijte volbu pluginu entry (ta řeší cesty relativně
ke root), nebo cesty pište relativně ke kořeni projektu, např. 'assets/app.js'.
To je vše! Nyní máte moderní build systém integrovaný s Nette Assets.