Symfony 4 : HTTP/2 et pré-chargement
Publié le 24 octobre 2017
Il y a quelques temps, notre équipe a ajouté un nouveau composant à Symfony : WebLink. En implémentant des standards récents tels que HTTP/2 et Resource Hints (du W3C), ce composant permet de booster les performances de votre WebApp.
Grâce au composant WebLink de Symfony, les serveurs HTTP/2 (h2) sont capables de pousser les ressources vers les clients avant même que ceux-ci ne sachent qu’ils en ont besoin (par exemple les fichiers JavaScript ou CSS, ou les relations d’une ressource exposée par une API). WebLink permet également d’autres optimisations qui fonctionnent avec HTTP/1 :
- Indiquer au navigateur d’aller récupérer ou d’effectuer le rendu d’une autre page web en arrière plan ;
- Initier les recherches DNS, les handshakes TCP ou les négociations TLS.
Découvrons ensemble les bénéfices immédiats qu’il apporte. Le composant WebLink est disponible depuis Symfony 3.3 (cela veut dire que vous pouvez commencer à l’utiliser dès maintenant), mais dans cet article, nous utiliserons Symfony 4 pour célébrer la sortie de sa première beta !
Pour commencer, téléchargez notre installateur de Symfony 4/Flex basé sur Docker. Il inclut tout ce dont vous avez besoin pour faire fonctionner Symfony (PHP 7.1 configuré correctement et Composer) ainsi qu’un reverse proxy (Apache) supportant HTTP/2 Server Push et HTTPS (la plupart des clients supportent uniquement HTTP/2 au travers d’une connexion TLS).
Décompressez le zip puis ouvrez un terminal dans le répertoire créé. Exécutez les commandes suivantes :
Ouvrez https://localhost. Si cette page apparaît, c’est que vous avez créé votre premier projet en Symfony 4 avec succès, et de surcroît vous le visitez via le protocole HTTP/2 !
Maintenant, nous allons créer une page d’accueil toute simple en utilisant le moteur de template Twig. Parce que Symfony Flex fonctionne comme un micro framework, la première étape sera d’installer cette bibliothèque (exécutez cette commande dans un nouveau terminal) : docker-compose exec app composer req twig.
Flex est assez malin pour télécharger Twig, l’enregistrer automatiquement dans Symfony et activer ses fonctionnalités. Il génère aussi un gabarit HTML5 de base dans le répertoire templates/ (nous ne l’utiliserons pas dans cet exemple mais vous vous recommandons de le faire).
Téléchargez Bootstrap 4, décompressez l’archive et copiez le fichier dist/css/bootstrap.min.css dans le répertoire public/ de notre projet. Comme vous le savez certainement : Symfony intègre désormais nativement Bootstrap 4 pour ses formulaires.
Note : vous pouvez aussi utiliser Yarn ou NPM avec Symfony Encore pour installer Bootstrap.
Il est temps de créer le template de votre page. Créez le fichier templates/homepage.html.twig comme suit :
Enfin, déclarez votre nouveau template en tant que homepage en utilisant le TemplateController.
Videz le cache : docker-compose exec app bin/console c:c (cette étape est maintenant optionnelle depuis que #24642 est mergée).
Rafraîchissez votre navigateur et vous verrez cette page apparaître :
Vous remarquerez que 2 requêtes HTTP sont effectuées par le navigateur, une pour la page Web et une pour Boostrap.
Nous savons depuis le départ que le navigateur aura besoin de Bootstrap. Au lieu d’attendre que le navigateur télécharge la page, analyse le HTML (“Initiator: Parser” dans Chrome DevTools), trouve une référence à bootstrap.min.css et envoie une nouvelle requête HTTP, nous pouvons bénéficier HTTP/2 Server Push afin de lui envoyer directement les deux ressources. C’est parti !
Installez le composant WebLink : docker-compose exec app composer req weblink
Comme pour Twig, Flex téléchargera et enregistrera automatiquement ce composant dans notre application. Maintenant, mettez à jour le template afin d’utiliser le helper preload de Twig qui exploite le composant de WebLink.
Rafraîchissez la page :
Comme vous pouvez le constater (Initiator: Push), les deux réponses ont été directement envoyées par le serveur. bootstrap.min.css a commencé à être récupéré avant même que le navigateur en ai fait la demande !
Comment ça marche ?
Le composant WebLink permet d’ajouter des en-têtes HTTP Link aux réponses. En référençant une ressource avec le helper preload(), un header Link ayant pour attribut rel=”preload” est ajouté à la réponse :
Selon la spécification Preload, quand un serveur HTTP/2 détecte que la réponse d’origine (HTTP/1) contient ce header HTTP, il va automatiquement déclencher un push du fichier référencé vers le client dans la même connection HTTP/2.
Le serveur Apache fourni par notre configuration Docker supporte cette fonctionnalité. C’est pour cela que Bootstrap est poussé vers le client ! La plupart des services de proxy et CDN (réseaux de diffusion de contenu) parmi lesquels Cloudfare, Fastly et Akamai tirent aussi parti de cette fonctionnalité.
Cela signifie que vous pouvez d’ores et déjà pousser les ressources en temps réel vers vos clients et améliorer les performances de vos applications en production ! Tout ce dont vous avez besoin est de Symfony 3.3+ et d’un serveur Web compatible (la version gratuite de Nginx ne supporte pas Server Push) ou un service de CDN.
Si vous ne souhaitez pas effectuer de push, mais souhaitez conserver la précharge par le navigateur en émettant une requête HTTP séparée, utilisez l’attribut nopush :
Avant d’utiliser HTTP/2 Server Push, soyez certain(e) de lire cet excellent article sur ses enjeux et l’état du support dans les navigateurs populaires.
En complément de HTTP/2 Server Push et de la pré-charge de resources, le composant WebLink permet également d’envoyer des resource hints aux clients comme :
- dns_prefetch : indique une origine qui sera utilisée pour récupérer les ressources demandées, et que le User-Agent devra résoudre le plus vite possible.
- preconnect : indique une origine qui sera utilisée pour récupérer dles ressources. Une connexion sera initiée ce qui inclut la recherche de DNS, le three-way handshake du protocole TCP, ainsi qu’une négociation TLS (si applicable). Cette méthode permet au client de masquer les coûts de latence de l’établissement de connexion.
- prefetch : identifie une ressource qui peut être demandée pour la prochaine navigation, et que le client devrait récupérer, de telle sorte qu’il puisse fournir une réponse plus rapide lorsque la ressource sera effectivement demandée.
- prerender : identifie une ressource qui peut être demandée pour la prochaine navigation, et que le client devrait récupérer et interpreter, de telle sorte qu’il puisse fournir une réponse plus rapide une fois que la ressource effectivement demandée.
Le composant WebLink peut aussi être utilisé pour envoyer un lien HTTP qui n’a pas trait à la performance. Par exemple, n’importe quel lien défini dans la spécification HTML :
L'exemple précédent provoquera l’envoi de cet en-tête HTTP au client :
Link: </index.jsonld>; rel="alternate",</bootstrap.min.css>; rel="preload"; nopush
Vous pouvez également ajouter des liens à la réponse HTTP directement depuis un contrôleur ou depuis n’importe quel autre service :
Enfin, comme tous les composants Symfony, WebLink peut être utilisé comme une bibliothèque PHP autonome :
Puisque nous parlons d'interopérabilité, WebLink peut gérer n’importe quel lien implémentant la PSR-13. Grâce à ce composant, il n’y a plus aucune excuse pour ne pas passer à HTTP/2 !
Découvrez-en davantage au sujet de ces nouvelles fonctionnalités dans les Pull Requests #22273 et #21478.
Votre appli Symfony présente quelques temps de latences ? Contactez-nous, nous vous aiderons à améliorer ses performances !
Symfony Community Awards
Vous avez aimé cet article et vous suivez de près les contributions Symfony de notre équipe ? Votez pour l'auteur de cet article à l'occasion des Symfony Community Awards qui auront lieu en novembre à l'occasion de la Symfony Con à Cluj (renseignez Dunglas dans le formulaire) !