Intégration de Vite
Les applications JavaScript modernes exigent des outils de build élaborés. Nette Assets offre une intégration de premier ordre avec Vite, l'outil de build frontend de nouvelle génération. Profitez d'un développement ultra-rapide avec le Hot Module Replacement (HMR) et de builds de production optimisés, sans le moindre casse-tête de configuration.
- Zéro configuration – pont automatique entre Vite et les templates PHP
- Gestion complète des dépendances – une seule balise s'occupe de tous les assets
- Hot Module Replacement – mises à jour instantanées du JavaScript et du CSS
- Builds de production optimisés – découpage du code et tree shaking
Nette Assets s'intègre parfaitement à Vite, si bien que vous profitez de tous ces avantages tout en écrivant vos templates comme d'habitude.
Mettre Vite en place
Mettons Vite en place pas à pas. Ne vous inquiétez pas si les outils de build sont nouveaux pour vous : nous expliquerons tout !
Étape 1 : installer Vite
Installez d'abord Vite et le plugin Nette dans votre projet :
npm install -D vite @nette/vite-plugin
Cela installe Vite et un plugin particulier qui l'aide à fonctionner parfaitement avec Nette.
Étape 2 : structure du projet
L'approche standard consiste à placer les fichiers sources des assets dans un dossier assets/ à la racine du
projet, et les versions compilées dans www/assets/ :
web-project/ ├── assets/ ← fichiers sources (SCSS, TypeScript, images sources) │ ├── public/ ← fichiers statiques (copiés tels quels) │ │ └── favicon.ico │ ├── images/ │ │ └── logo.png │ ├── app.js ← point d'entrée principal │ └── style.css ← vos styles └── www/ ← répertoire public (document root) ├── assets/ ← les fichiers compilés arriveront ici └── index.php
Le dossier assets/ contient vos fichiers sources, le code que vous écrivez. Vite traitera ces fichiers et placera
les versions compilées dans www/assets/.
Étape 3 : configurer Vite
Créez un fichier vite.config.ts à la racine de votre projet. Ce fichier indique à Vite où trouver vos fichiers
sources et où placer les fichiers compilés.
Le plugin Vite de Nette est livré avec des valeurs par défaut intelligentes qui simplifient la configuration. Il suppose que
vos fichiers sources front-end sont dans le répertoire assets/ (option root) et que les fichiers
compilés vont dans www/assets/ (option outDir). Vous n'avez qu'à indiquer le point d'entrée :
import { defineConfig } from 'vite';
import nette from '@nette/vite-plugin';
export default defineConfig({
plugins: [
nette({
entry: 'app.js',
}),
],
});
Sous le capot, outre root et outDir, le plugin définit quelques autres options de Vite pour que tout
s'emboîte : base à '' (les assets sont servis directement depuis le document root),
build.manifest à true (pour que Nette Assets puisse associer les noms de fichiers hachés) et
build.assetsDir à '' (les fichiers compilés atterrissent directement dans outDir, sans
sous-dossier static/). Vous pouvez redéfinir chacune d'elles.
L'outDir par défaut (www/assets) exige que le répertoire www/ existe
déjà. Sinon, le plugin s'arrête avec l'erreur „The output directory … does not exist“.
Si vous voulez indiquer un autre nom de répertoire pour construire vos assets, vous devrez changer quelques options :
export default defineConfig({
root: 'assets', // répertoire racine des assets sources
build: {
outDir: '../www/assets', // où vont les fichiers compilés
},
// ... autre configuration ...
});
Le chemin outDir est considéré comme relatif à root, d'où le ../
au début.
Étape 4 : configurer Nette
Parlez de Vite à Nette Assets dans votre common.neon :
assets:
mapping:
default:
type: vite # indique à Nette d'utiliser le ViteMapper
path: assets
Étape 5 : ajouter les scripts
Ajoutez ces scripts à votre package.json :
{
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
Vous pouvez désormais :
npm run dev– démarrer le serveur de développement avec rechargement à chaudnpm run build– créer les fichiers de production optimisés
Points d'entrée
Un point d'entrée est le fichier principal par lequel votre application commence. Depuis ce fichier, vous importez d'autres fichiers (CSS, modules JavaScript, images), ce qui crée un arbre de dépendances. Vite suit ces imports et regroupe le tout.
Exemple de point d'entrée assets/app.js :
// Import des styles
import './style.css'
// Import des modules JavaScript
import netteForms from 'nette-forms';
import naja from 'naja';
// Initialisation de votre application
netteForms.initOnLoad();
naja.initialize();
Dans le template, vous pouvez insérer un point d'entrée ainsi :
{asset 'app.js'}
Nette Assets génère automatiquement toutes les balises HTML nécessaires – JavaScript, CSS et toutes les autres dépendances.
Plusieurs points d'entrée
Les applications plus grandes ont souvent besoin de points d'entrée distincts :
export default defineConfig({
plugins: [
nette({
entry: [
'app.js', // pages publiques
'admin.js', // panneau d'administration
],
}),
],
});
Utilisez-les dans différents templates :
{* Dans les pages publiques *}
{asset 'app.js'}
{* Dans le panneau d'administration *}
{asset 'admin.js'}
Important : fichiers sources et fichiers compilés
Il est essentiel de comprendre qu'en production vous ne pouvez charger que les fichiers que Vite met à disposition, soit par son manifest, soit en les copiant tels quels depuis le dossier public :
- Les points d'entrée définis dans
entry(y compris les modules qu'ils importent dynamiquement) et les assets référencés depuis le JavaScript ou le CSS (images, polices, …) – tous sont consignés dans le manifest - Les fichiers du répertoire
assets/public/– ceux-là ne sont pas dans le manifest ; ils sont copiés tels quels et{asset}les localise par un repli sur le système de fichiers
Vous ne pouvez pas charger avec {asset} n'importe quel fichier d'assets/ : si un fichier n'est
référencé nulle part, il ne sera pas compilé. Si vous voulez faire connaître d'autres assets à Vite, vous pouvez les
déplacer dans le dossier public.
Notez que, par défaut, Vite intègre en ligne tous les assets de moins de 4 Ko, vous ne pourrez donc pas référencer ces fichiers directement. (Voir la documentation de Vite).
{* ✓ Cela fonctionne - c'est un point d'entrée *}
{asset 'app.js'}
{* ✓ Cela fonctionne - c'est dans assets/public/ *}
{asset 'favicon.ico'}
{* ✗ Cela ne fonctionnera pas - fichier quelconque dans assets/ *}
{asset 'components/button.js'}
Mode développement
Le mode développement est totalement facultatif, mais il apporte de gros avantages une fois activé. Le principal est le Hot Module Replacement (HMR) : vous voyez les changements instantanément sans perdre l'état de l'application, ce qui rend le développement bien plus fluide et rapide.
Vite est un outil de build moderne qui rend le développement incroyablement rapide. Contrairement aux bundlers traditionnels, Vite sert votre code directement au navigateur pendant le développement, ce qui signifie un démarrage instantané du serveur quelle que soit la taille du projet et des mises à jour éclair.
Démarrer le serveur de développement
Lancez le serveur de développement :
npm run dev
Vous verrez :
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Gardez ce terminal ouvert pendant le développement.
Tant que le serveur de développement tourne, le plugin écrit un petit fichier signal www/assets/.vite/nette.json
contenant son URL. Côté PHP, Nette Assets lit ce fichier et bascule sur le chargement depuis le serveur de développement
lorsque les deux conditions suivantes sont remplies :
- le serveur de développement Vite tourne (le fichier signal existe), et
- votre application Nette est en mode débogage.
Le résultat :
{asset 'app.js'}
{* En développement : <script src="http://localhost:5173/@vite/client" type="module"></script>
<script src="http://localhost:5173/app.js" type="module"></script> *}
{* En production : <script src="/assets/app-4f3a2b1c.js" type="module" crossorigin></script> *}
Aucune configuration n'est nécessaire, cela fonctionne tout seul ! Pour désactiver la détection ou indiquer manuellement l'URL du serveur de développement, voir l'option devServer.
Le fichier signal se trouve dans www/assets/.vite/nette.json (juste à côté du
manifest.json de production). Vous pouvez le renommer avec l'option infoFile du plugin, qui vaut
.vite/nette.json par défaut. Si Nette ne détecte pas le serveur de développement en cours, vérifiez que ce
fichier existe et pointe vers la bonne URL.
Travailler sur des domaines différents
Si votre serveur de développement tourne ailleurs que sur localhost (par exemple sur myapp.local),
vous pouvez rencontrer des problèmes de CORS (Cross-Origin Resource Sharing). Le CORS est une fonction de sécurité des
navigateurs web qui bloque par défaut les requêtes entre domaines différents. Quand votre application PHP tourne sur
myapp.local mais que Vite tourne sur localhost:5173, le navigateur les voit comme des domaines
différents et bloque les requêtes.
Vous avez deux possibilités pour régler cela :
Option 1 : configurer le CORS
La solution la plus simple est d'autoriser les requêtes cross-origin venant de votre application PHP :
export default defineConfig({
// ... autre configuration ...
server: {
cors: {
origin: 'http://myapp.local', // l'URL de votre application PHP
},
},
});
Option 2 : faire tourner Vite sur votre domaine
L'autre solution est de faire tourner Vite sur le même domaine que votre application PHP.
export default defineConfig({
// ... autre configuration ...
server: {
host: 'myapp.local', // le même que votre application PHP
},
});
En réalité, même dans ce cas, vous devez configurer le CORS, car le serveur de développement tourne sur le même nom d'hôte mais sur un port différent. Ici, cependant, le CORS est configuré automatiquement par le plugin Vite de Nette.
Développement en HTTPS
Si vous développez en HTTPS, vous avez besoin de certificats pour votre serveur de développement Vite. Le plus simple est d'utiliser un plugin qui génère les certificats automatiquement :
npm install -D vite-plugin-mkcert
Voici comment le configurer dans vite.config.ts :
import mkcert from 'vite-plugin-mkcert';
export default defineConfig({
// ... autre configuration ...
plugins: [
mkcert(), // génère les certificats automatiquement et active https
nette(),
],
});
Notez que si vous utilisez la configuration CORS (option 1 ci-dessus), vous devez mettre à jour l'URL d'origine pour utiliser
https:// au lieu de http://.
Développement avec Docker
Quand vous faites tourner Vite dans un conteneur Docker, deux points demandent votre attention : le navigateur de votre machine doit pouvoir joindre le serveur de développement, et Vite doit détecter les changements de fichiers au travers de la frontière du conteneur.
Commencez par publier le port de Vite depuis le conteneur et liez le serveur de développement à toutes les interfaces, afin qu'il soit joignable depuis l'extérieur du conteneur :
export default defineConfig({
// ... autre configuration ...
plugins: [
nette(),
],
server: {
host: '0.0.0.0', // écoute sur toutes les interfaces (nécessaire dans un conteneur)
port: 5173, // doit correspondre au port publié
strictPort: true, // échouer plutôt que choisir un autre port
watch: {
usePolling: true, // à activer si les changements de fichiers ne sont pas détectés sur les volumes montés
},
},
});
Le plugin écrit l'URL du serveur de développement dans nette.json pour le côté PHP. Comme
host: '0.0.0.0' n'est pas utilisable par un navigateur (il redirige vers localhost pour chaque asset),
le plugin la réécrit automatiquement en localhost dans cette URL, afin que les assets se chargent correctement.
Si vous ouvrez l'application sur un domaine personnalisé plutôt que sur localhost, définissez l'option
host du plugin sur ce domaine :
plugins: [
nette({ host: 'myapp.local' }), // le même domaine que votre application PHP
],
Le plugin utilise alors cet hôte pour l'URL du serveur de développement, l'ajoute aux origines CORS et le met dans la liste
blanche allowedHosts de Vite – cela fonctionne donc sans aucun réglage CORS manuel.
Pour des installations plus complexes – par exemple quand Vite tourne derrière un reverse proxy où l'hôte public, le port
et le protocole diffèrent tous de l'adresse interne – définissez server.origin de Vite sur l'URL publique
complète. Le plugin la respecte et l'écrit telle quelle dans nette.json, au lieu de déduire l'URL du socket
local :
server: {
origin: 'https://myapp.local:8443', // l'URL publique par laquelle le navigateur atteint Vite
},
Builds de production
Créez les fichiers de production optimisés :
npm run build
Vite va :
- minifier tout le JavaScript et le CSS
- découper le code en morceaux optimaux
- générer des noms de fichiers hachés pour invalider le cache
- créer un fichier manifest pour Nette Assets
Exemple de sortie :
www/assets/
├── app-4f3a2b1c.js # Votre JavaScript principal (minifié)
├── app-7d8e9f2a.css # CSS extrait (minifié)
├── vendor-8c4b5e6d.js # Dépendances partagées
└── .vite/
└── manifest.json # Correspondances pour Nette Assets
Les noms de fichiers hachés garantissent que les navigateurs chargent toujours la dernière version.
Dossier public
Les fichiers du répertoire assets/public/ sont copiés vers la sortie sans traitement :
assets/
├── public/
│ ├── favicon.ico
│ ├── robots.txt
│ └── images/
│ └── og-image.jpg
├── app.js
└── style.css
Référencez-les normalement :
{* Ces fichiers sont copiés tels quels *}
<link rel="icon" href={asset 'favicon.ico'}>
<meta property="og:image" content={asset 'images/og-image.jpg'}>
Pour les fichiers publics, vous pouvez utiliser les fonctionnalités de FilesystemMapper. L'option extension
s'applique aux références sans extension (par exemple {asset 'images/og-image'} trouve d'abord
og-image.webp) :
assets:
mapping:
default:
type: vite
path: assets
extension: [webp, jpg, png] # pour les références sans extension
versioning: true # Ajoute l'invalidation du cache
Dans la configuration vite.config.ts, vous pouvez changer le dossier public à l'aide de l'option
publicDir.
Imports dynamiques
Vite découpe automatiquement le code pour un chargement optimal. Les imports dynamiques vous permettent de ne charger du code que lorsqu'il est réellement nécessaire, ce qui réduit la taille du bundle initial :
// Charge les composants lourds à la demande
button.addEventListener('click', async () => {
let { Chart } = await import('./components/chart.js')
new Chart(data)
})
Les imports dynamiques créent des chunks distincts qui ne sont chargés qu'au besoin. C'est ce qu'on appelle le „code splitting“, l'une des fonctionnalités les plus puissantes de Vite. Quand vous utilisez des imports dynamiques, Vite crée automatiquement des fichiers JavaScript distincts pour chaque module importé dynamiquement.
La balise {asset 'app.js'} ne précharge pas automatiquement ces chunks dynamiques. C'est un comportement
voulu : nous ne voulons pas télécharger du code qui pourrait ne jamais servir. Les chunks ne sont téléchargés qu'au moment
où l'import dynamique s'exécute.
Si vous savez cependant que certains imports dynamiques sont critiques et seront bientôt nécessaires, vous pouvez les précharger :
{* Point d'entrée principal *}
{asset 'app.js'}
{* Précharge les imports dynamiques critiques *}
{preload 'components/chart.js'}
Cela dit au navigateur de télécharger le composant chart en arrière-plan, afin qu'il soit prêt dès qu'on en aura besoin.
Prise en charge de TypeScript
TypeScript fonctionne immédiatement :
// assets/main.ts
interface User {
name: string
email: string
}
export function greetUser(user: User): void {
console.log(`Hello, ${user.name}!`)
}
Référencez les fichiers TypeScript normalement (comme pour tout fichier, main.ts doit être un point
d'entrée) :
{asset 'main.ts'}
Pour une prise en charge complète de TypeScript, installez-le :
npm install -D typescript
Configuration supplémentaire de Vite
Voici quelques options de configuration utiles de Vite, avec des explications détaillées :
export default defineConfig({
// Répertoire racine contenant les assets sources
root: 'assets',
// Dossier dont le contenu est copié tel quel vers le répertoire de sortie
// Par défaut : 'public' (relatif à 'root')
publicDir: 'public',
build: {
// Où placer les fichiers compilés (relatif à 'root')
outDir: '../www/assets',
// Vider le répertoire de sortie avant le build ?
// Utile pour supprimer les anciens fichiers des builds précédents
emptyOutDir: true,
// Sous-répertoire d'outDir pour les chunks et assets générés
// Cela aide à organiser la structure de sortie
assetsDir: 'static',
rollupOptions: {
// Point(s) d'entrée - un seul fichier ou un tableau de fichiers
// Chaque point d'entrée devient un bundle distinct
input: [
'app.js', // application principale
'admin.js', // panneau d'administration
],
},
},
server: {
// Hôte auquel lier le serveur de développement
// Utilisez '0.0.0.0' pour l'exposer au réseau
host: 'localhost',
// Port du serveur de développement
port: 5173,
// Configuration CORS pour les requêtes cross-origin
cors: {
origin: 'http://myapp.local',
},
},
css: {
// Activer les source maps CSS en développement
devSourcemap: true,
},
plugins: [
nette(),
],
});
Attention aux chemins des points d'entrée dans rollupOptions.input ci-dessus : Rollup résout les
chemins relatifs par rapport au répertoire de travail courant (la racine de votre projet), et non par rapport à
root: 'assets'. Un simple 'app.js' n'existera donc pas au moment du build. Utilisez soit l'option
entry du plugin (qui résout les chemins des points d'entrée relativement à root), soit écrivez les
chemins relativement à la racine du projet, par exemple 'assets/app.js'.
C'est tout ! Vous disposez maintenant d'un système de build moderne intégré à Nette Assets.