Après plusieurs années de bons et loyaux services, Mix laissera finalement sa place à Vite à partir de Laravel 9.
Plus moderne et surtout plus rapide, Vite est un puissant tooling front qui compilera vos assets CSS et JS à la vitesse de la lumière.
Une fois intégré à Laravel, Vite dispose de deux modes de fonctionnement.
Le mode dev, accessible avec la commande npm run dev
, offrant un performant système de hot reload recompilant à chaud toutes vos assets JS et CSS.
Ainsi qu'un mode build ,npm run build
, adapté à la production, compressant et minifiant toutes vos assets.
Pour intégrer ces assets, rien de plus simple, Laravel propose une nouvelle directive @vite()
:
1@vite(['resources/css/app.css', 'resources/js/app.js'])
Ces deux modes de fonctionnement sont clairement visibles dans votre HTML, la directive @vite
intégrera automatiquement les bonnes assets selon le mode que vous utilisez :
1# npm run dev2<script type="module" src="http://localhost:5173/@vite/client"></script>3<script type="module" src="http://localhost:5173/resources/js/app.js">4 5# npm run build6<link rel="stylesheet" href="http://localhost:8089/build/assets/app.5c5855fa.css" />7<script type="module" src="http://localhost:8089/build/assets/app.64e7ccdb.js"></script>
5173 est le port par défaut du serveur hot reload
Cependant, l’intégration de Vite à Laravel est encore jeune et il subsiste des zones d’ombre ou des nouvelles habitudes à prendre.
Par exemple, il est possible qu’après avoir lancé avec succès un npm run dev
que l'application reste bloquée en mode Dev et que vous n'arriviez plus à build les assets.
La directive @vite()
continuera d'inclure le serveur de hot reload alors que vous désirez utiliser les assets compilées.
Laissez-moi vous présenter en quelques minutes un retour d'expérience douloureux sur Vite !
La directive vite
La directive @vite()
se cache dans la class CompilesHelpers
au même niveau que les directives @dd()
et @crsf()
:
1protected function compileVite($arguments)2{3 $arguments ??= '()';4 5 $class = Vite::class;6 7 return "<?php echo app('$class'){$arguments}; ?>";8}
Son code est plutôt succinct, la méthode se contente de manipuler une instance de Illuminate\Foundation\Vite
.
Vite
est une class invokable, son point d’entrée est donc la méthode __invoke
.
1public function __invoke($entrypoints, $buildDirectory = 'build')2{3 static $manifests = [];4 5 $entrypoints = collect($entrypoints);6 $buildDirectory = Str::start($buildDirectory, '/');7 8 if (is_file(public_path('/hot'))) {9 $url = rtrim(file_get_contents(public_path('/hot')));
Un élément saute rapidement aux yeux, la méthode __invoke
vérifie la présence d’un fichier /hot
à la racine du dossier public.
1if (is_file(public_path('/hot'))) {
Si ce fichier est présent, alors la directive considère que l’application est en mode dev et cherchera à contacter le serveur de hot reload.
ce fichier
hot
est ignoré par votre.gitignore
, il n’apparaitra pas dans vos fichiers versionnés
Dans un second temps, la directive vérifiera la présence du fichier manifest.json
lui assurant que l’application possède bien des assets compilées et en conclura que l’application est en mode build.
Nous savons désormais comment s’effectue la balance entre le mode dev et build, il reste toujours deux questions en suspend : comment est manipulé ce fichier hot
et dans quelles circonstances l’application peut se retrouver bloquée en mode dev ?
Le fichier hot
C’est le plugin JS laravel-vite-plugin qui détient la responsabilité de manipuler ce fichier /hot
depuis laravel-vite-plugin\dist\index.js
.
Ce plugin simplifie l'intégration de Vite à un backend Laravel.
On remarque rapidement que le fichier /hot
est tout simplement créé lors du lancement du serveur de hot reload :
1const hotFile = path_1.default.join(pluginConfig.publicDirectory, 'hot');2 3//4 5fs_1.default.writeFileSync(hotFile, viteDevServerUrl);
Et que ce fichier est supprimé lors de la fermeture de ce même serveur :
1const clean = () => { 2 if (fs_1.default.existsSync(hotFile)) { 3 fs_1.default.rmSync(hotFile); 4 } 5}; 6 7process.on('exit', clean); 8process.on('SIGINT', process.exit); 9process.on('SIGTERM', process.exit);10process.on('SIGHUP', process.exit)
La suppression du fichier hot
s'effectue en vérifiant les signaux systèmes, si la commande détecte un signal de sortie elle utilisera sa méthode clean
, supprimant le fichier hot
, avant de fermer le serveur.
Un SIGTERM est le signal envoyé vers le serveur en faisant un
ctrl + c
Conclusion
Nous avons désormais toutes les cartes en main.
Nous savons que la présence du fichier hot
détermine le status de l'application, que ce fichier est ignoré par git
et qu’il est supprimé lors de la fermeture du serveur de hot reload.
Le cœur du problème est là, il est nécessaire que le serveur de hot reload soit proprement fermé (à l’aide d’un signal système) pour que le fichier hot
soit correctement supprimé.
Désormais, imaginez un docker capricieux qui explose, une coupure de courant, n'importe quel évènement chaotique … ce fichier hot
deviendra orphelin et le jeu des permissions pourront le rendre inaccessible à un futur lancement de la commande npm run dev
.
Le fichier hot
restera présent à la racine du dossier /public
, invisible à vos yeux, et bloquera toute tentative de build l’application … et vous passerez une bonne après-midi à comprendre ce qu’il se passe !
A lire
Autres articles de la même catégorie
PHPStan valide nos règles de conception
Comment s’assurer du respect de nos règles de conception ? Avec PHPStan bien sûr !
William Suppo
Explorons la nouvelle class Process
Voyons un cas concret d'utilisation de la class Process pour améliorer nos performances
Mathieu De Gracia
Les bases 2/6 : Création du contrôleur
Découverte des contrôleurs au sein d'une application Laravel
William Suppo