• 30 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

Ce cours existe en livre papier.

course.header.alt.is_certifying

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 04/09/2017

Utiliser Assetic pour gérer les codes CSS et JS de votre site

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

La gestion des ressources CSS et JavaScript dans un site Internet est très importante et n'est pas si évidente ! Leur chargement est très souvent le point le plus lent pour l'affichage de la page à vos visiteurs, ce n'est donc pas quelque chose à négliger.

Pour vous aider à gérer ces ressources efficacement, Symfony2 intègre un bundle nommé Assetic qui va s'occuper de tout cela à votre place. Il va vous permettre d'optimiser au maximum le chargement de ces ressources pour vos visiteurs. Vous verrez, ce bundle est presque magique !

Théorie : entre vitesse et lisibilité, pourquoi choisir ?

À propos du nombre de requêtes HTTP d'une page web

Vous devez sûrement vous demander ce que vient faire la vitesse d'une page dans une section qui traite de code CSS. C'est une bonne question et je vais y répondre. Le temps de chargement ressenti d'une page par un visiteur comprend tout le processus du clic au rendu de la page par le navigateur. Ainsi, on y inclut :

  • Le temps d'envoi de la requête au serveur lors du clic. On ne peut pas y faire grand-chose, malheureusement.

  • Le temps d'exécution de la page côté serveur, le temps PHP, donc. Pour cela, il faut bien penser son script et essayer de l'optimiser un peu.

  • Le temps d'envoi du code HTML par le serveur vers le navigateur. On ne peut pas y faire grand-chose non plus.

  • Mais là ce n'est pas tout : à partir de cette page HTML que le navigateur reçoit, ce dernier doit tout recommencer pour chaque fichier CSS, chaque JavaScript et chaque image !

Donc si votre page contient 5 fichiers CSS, 3 JavaScript et 15 images, cela fait un total de 23 requêtes HTTP à traiter par votre navigateur pour vous afficher l'intégralité de la page ! Et pour ces 23 requêtes, il y a les temps d'envoi et de réception qui sont incompressibles et qui prennent du temps.

Au final, s'il faut bien sûr optimiser le code PHP côté serveur, la partie front-end qui comprend codes HTML, CSS et JavaScript ainsi que les fichiers images est bien celle qui prend le plus de temps à se charger, vu du visiteur.

Comment optimiser le front-end ?

L'idée est de réduire les temps incompressibles. Comme ils sont justement incompressibles, il faut que l'on en diminue le nombre. La seule solution est donc de grouper ces fichiers. L'idée est que, au lieu d'avoir cinq fichiers CSS différents, on va mettre tout notre code CSS dans un seul fichier. Comme cela, on aura une seule requête au lieu de cinq. Super !

Mais le problème, c'est que si l'on avait trois fichiers et non un seul, ce n'était pas pour rien. Chaque fichier concernait une partie de votre site, c'était bien plus lisible. Tout regrouper vous gênerait dans le développement de vos fichiers CSS (idem pour les fichiers JavaScript, bien sûr).

C'est là qu'Assetic va intervenir : il va grouper lui-même les fichiers et va vous permettre de garder votre séparation !

Il est aussi possible d'améliorer le temps de chargement !

En effet, transmettre votre unique fichier CSS de plusieurs centaines de lignes, cela prend du temps (temps qui varie en fonction de la connexion de votre serveur, de celle du visiteur, etc.). On peut améliorer ce temps en diminuant simplement la taille du fichier.

C'est possible grâce à un outil Java appelé YUI Compressor, un outil développé par Yahoo!. Cet outil permet de diminuer la taille de vos fichiers CSS, mais surtout de vos fichiers JavaScript, en supprimant les commentaires, les espaces, en raccourcissant le nom des variables, etc. On dit qu'il « minifie » les fichiers (il ne les compresse pas comme un fichier zip). Le code devient bien sûr complètement illisible ! Mais c'est là qu'Assetic intervient de nouveau : il vous permet de garder votre version claire lorsque vous développez, mais « minifie » les fichiers pour vos visiteurs (en mode prod) !

En action !

Vous voulez voir ce que donne l'utilisation d'Assetic sur un vrai site internet pour bien vous rendre compte ? Je vous invite à regarder la source d'un site que j'ai réalisé, Caissin.fr, dans lequel j'utilise Assetic. Le chargement de tous les fichiers CSS se fait en 3 lignes :

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css">
<link href="/assets/css/style.css">

Ce qui nous intéresse, c'est le dernier fichier, que j'ai nomméstyle.css. C'est ce fichier qui contient tous mes CSS perso. Ouvrez-le, vous pouvez voir que son contenu est difficilement lisible : pas d'indentation, pas d'espaces, etc. C'est cela qu'on appelle la « minification ». Vous pouvez également voir qu'il y a plusieurs fichiers concaténés en un seul. Bref, ce fichier est très dense et permet d'optimiser le chargement de tous les CSS du site, efficace !

Il en est de même avec le fichier Javascript, je vous laisse regarder ce que cela donne.

Conclusion

Grâce à Assetic, on peut optimiser très facilement nos scripts CSS/JS. Par exemple, nous pouvons passer de nos huit requêtes pour 500 Ko à seulement deux requêtes (1 CSS + 1 JS) pour 200 Ko. Le temps d'affichage de la page pour nos visiteurs sera donc bien plus court, et on conserve la lisibilité du code côté développeur !

Pratique : Assetic à la rescousse !

Assetic est déjà activé par défaut dans Symfony2, donc vous n'avez rien à faire de ce côté, vous pouvez l'utiliser directement. L'objectif d'Assetic est de regrouper nos fichiers CSS et JavaScript comme nous venons d'en parler.

Servir des ressources

Assetic peut servir au navigateur les ressources que vous lui demandez.

Servir une seule ressource

Allez donc dans la vue du layout, nous allons y déclarer nos fichiers CSS et JavaScript. Voici comment on déclarait nos fichiers CSS jusqu'à maintenant :

{# app/Resources/views/layout.html.twig #}

<link rel="stylesheet" href="{{ asset('bundles/ocplatform/css/main.css') }}" type="text/css" />

Et voici comment faire pour décharger cette responsabilité à Assetic :

{# app/Resources/views/layout.html.twig #}

{% stylesheets '@OCPlatformBundle/Resources/public/css/main.css' %}
  <link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
{% endstylesheets %}

Et voici le HTML qu'Assetic a généré avec cette balise :

<link rel="stylesheet" href="/Symfony/web/app_dev.php/css/519c4f6_main_1.css" type="text/css" />

Pas convaincant ? C'est parce que nous sommes en mode dev ! Nous verrons plus loin comment nous occuper du mode prod, qui demande un peu d'effort.

En attendant, essayons de comprendre ce code généré. En mode dev, Assetic génère à la volée les ressources, d'où une URL vers un fichier CSS qui passe par le contrôleur frontalapp_dev.php. En réalité, c'est bien un contrôleur d'Assetic qui s'exécute, car le fichierapp_dev.php/css/519c4f6_main_1.cssn'existe évidemment pas. Ce contrôleur va chercher le contenu du fichier qu'on lui a indiqué, puis le retransmet. Pour l'instant il le retransmet tel quel, mais il sera bien sûr possible d'appliquer des modifications, nous le verrons par la suite.

Et bien sûr, le mécanisme est exactement le même pour vos fichiers JavaScript :

{# app/Resources/views/layout.html.twig #}

{% javascripts '@OCPlatformBundle/Resources/public/js/main.js' %}
  <script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
Servir plusieurs ressources regroupées en une

Cela devient déjà un peu plus intéressant. En plus du fichier CSSmain.css(ou tout autre fichier, adaptez au code que vous avez bien sûr), on va charger le fichierbootstrap.cssqui est directement dansweb/css. Avec l'ancienne méthode, on aurait écrit une deuxième balise<link>, mais voici comment faire avec Assetic :

{# app/Resources/views/layout.html.twig #}

{% stylesheets
  '@OCPlatformBundle/Resources/public/css/main.css'
  'css/bootstrap.css' %}
  <link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
{% endstylesheets %}

On a simplement rajouté la deuxième ressource à charger dans la balisestylesheets. Et voici le rendu HTML :

<link rel="stylesheet" href="/Symfony/web/app_dev.php/css/03b7e21_main_1.css" type="text/css" />
<link rel="stylesheet" href="/Symfony/web/app_dev.php/css/03b7e21_bootstrap_2.css" type="text/css" />

Mais il n'était pas censé regrouper les deux ressources en une ?

Si bien sûr… mais en mode prod ! Encore une fois, nous sommes en mode de développement, il est donc inutile de regrouper les ressources (on se fiche un peu de la rapidité), Assetic ne le fait donc pas.

Si vous avez plusieurs fichiers CSS dans le répertoire des CSS de votre bundle, il est également possible d'utiliser un joker pour les charger tous. Ainsi, au lieu de préciser les fichiers exacts :

{# app/Resources/views/layout.html.twig #}

{% stylesheets
  '@OCPlatformBundle/Resources/public/css/main.css'
  '@OCPlatformBundle/Resources/public/css/autre.css' %}

Vous pouvez utiliser le joker « * », comme ceci :

{# app/Resources/views/layout.html.twig #}

{% stylesheets '@OCPlatformBundle/Resources/public/css/*' %}

Ce qui chargera tous les fichiers qui sont dans le répertoire, pratique !

Modifier les ressources servies

En servant les ressources depuis un contrôleur PHP, Assetic a la possibilité de modifier à la volée tout ce qu'il sert. Cela est possible grâce aux filtres, que l'on peut définir directement dans les balisesstylesheetsoujavascripts.

Voyons quelques filtres intéressants.

Le filtrecssrewrite

Si vous avez exécuté le code précédent, vous avez dû vous rendre compte qu'il se pose un petit problème : les images utilisées par le CSS debootstrapont disparu. En effet, le fichier CSS debootstrapfait référence aux images via le chemin relatif../img/exemple.png.

Lorsque le fichier CSS était placé dansweb/css, ce chemin relatif pointait bien versweb/img, là où sont nos images. Or maintenant, du point de vue du navigateur, le fichier CSS est dansapp_dev.php/css, du coup le chemin relatif vers les images n'est plus bon !

C'est ici qu'intervient le filtrecssrewrite. Voici la seule modification à apporter côté vue Twig :

{# app/Resources/views/layout.html.twig #}

{% stylesheets filter='cssrewrite'
  '@OCPlatformBundle/Resources/public/css/main.css'
  'css/bootstrap.css' %}
  <link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
{% endstylesheets %}

On a juste précisé l'attributfilterà la balise. Ce filtre permet de réécrire tous les chemins relatifs contenus dans les fichiers CSS, afin de prendre en compte la modification du répertoire du CSS. Actualisez votre page, vous verrez que cela fonctionne très bien ! Le chemin relatif d'accès aux images est devenu :../../img/exemple.png, ce qui est bon.

Les filtresyui_cssetyui_js

Ces filtres sont très utiles, ce sont ceux qui « minifient » les fichiers avec YUI Compressor.

Pour utiliser l'outil YUI Compressor, il faut que vous le téléchargiez manuellement. Copiez le fichier (version2.4.8-preà l'heure où j'écris ces lignes) dans le répertoireapp/Resources/java, par exemple. Maintenant, direction la configuration de notre application, il y a une section sur Assetic pour lui dire où nous avons mis Yui Compressor. Modifiez la partieassetic:comme suit :

# app/config/config.yml

# Assetic Configuration
assetic:
    debug:          %kernel.debug%
    use_controller: false
    # java: /usr/bin/java
    filters:
        cssrewrite: ~
        yui_js:
            jar: %kernel.root_dir%/Resources/java/yuicompressor.jar
        yui_css:
            jar: %kernel.root_dir%/Resources/java/yuicompressor.jar

Voilà, nous venons d'activer les filtresyui_jsetyui_css, on peut maintenant les utiliser depuis nos vues. Ajoutez ce filtre dans vos balises :

{# app/Resources/views/layout.html.twig #}

{% stylesheets  filter='cssrewrite, yui_css'
  ... %}

Et de même pour les fichiers JavaScript :

{# app/Resources/views/layout.html.twig #}

{% javascripts filter='yui_js'
  ... %}

Testez le rendu !

Mais… on est toujours en mode dev et les fichiers sont devenus illisibles pour un éventuel débogage ! Heureusement, vous avez la possibilité de dire qu'un filtre ne s'applique pas en mode dev. Il suffit de mettre un point d'interrogation devant :

{# app/Resources/views/layout.html.twig #}

{% stylesheets filter='?yui_css'
  ... %}

Ainsi, le filtre ne s'appliquera qu'en mode prod, tout comme le groupement des fichiers en un seul.

Au final, notre mode dev n'a pas changé d'un poil, on garde nos différents fichiers et ces derniers sont lisibles, mais le mode prod a reçu toutes les optimisations : regroupement des fichiers ainsi que « minification ».

Gestion du mode prod

Si vous n'avez pas encore testé le rendu en mode prod, faites-le. Cela ne fonctionne pas ? Vos fichiers CSS et JS ne sont pas chargés ? C'est normal. :p Nous n'avons pas fini notre mise en place.

Comprendre Assetic

Pour comprendre pourquoi la gestion du mode prod demande un effort supplémentaire, vous devez comprendre la manière dont Assetic fonctionne. Lorsque l'on utilise les balises{% stylesheets %}ou{% javascripts %}, le code HTML généré en mode prod est le suivant (regardez la source de vos pages HTML) :

<link rel="stylesheet" href="/Symfony/web/css/cd91cad.css" type="text/css" />

Or ce fichier n'existe pas du tout !

Lors du mode dev, on l'a vu, Assetic passe directement par un contrôleur pour générer à la volée nos ressources. Mais évidemment, « minifier » et regrouper des fichiers à la volée et ce pour chaque requête, cela prend beaucoup de temps. Si en mode dev on peut se le permettre, on ne le peut pas en mode prod !

Du coup, l'astuce pour le mode prod est d'exporter en dur, une bonne fois pour toutes, les fichiers CSS et JS dont on a besoin. Ainsi, en mode prod, le fichier/css/cd91cad.css(dans mon cas) existera en dur, Assetic n'interceptera pas l'URL, et votre serveur web (souvent Apache) va envoyer directement le contenu du fichier à vos visiteurs. Plus rapide, on ne peut pas !

Exporter ses fichiers CSS et JS

Pour faire cet export en dur, il faut utiliser une simple commande d'Assetic :

php app/console assetic:dump --env=prod

Cette commande devrait vous sortir un résultat de ce type :

C:\wamp\www\Symfony>php app/console assetic:dump --env=prod
Dumping all prod assets.
Debug mode is off.

16:13:30 [file+] C:/wamp/www/Symfony/app/../web/css/cd91cad.css

Cette commande va lire toutes nos vues pour y trouver les balises{% stylesheets %}et{% javascripts %}, puis va exporter en dur dans les fichiers/web/css/XXX.csset/web/js/XXX.js.

Et voilà, maintenant, nos fichiers existent réellement. Testez à nouveau le rendu en mode prod : c'est bon !

Et bien plus encore…

Assetic, c'est une bibliothèque complète qui permet beaucoup de choses. Vous pouvez également optimiser vos images, et construire une configuration plus poussée. Bref, n'hésitez pas à vous renseigner sur la documentation officielle.

En réumé

  • Le chargement des fichiers CSS et JS prend beaucoup de temps dans le rendu d'une page HTML sur le navigateur de vos visiteurs ;

  • Assetic permet de regrouper tous vos fichiers CSS ainsi que tous vos fichiers JS, afin de réduire le nombre de requêtes HTTP que doivent faire vos visiteurs pour afficher une page ;

  • Assetic permet également de minifier vos fichiers, afin de diminuer leur taille et donc accélérer leur chargement pour vos visiteurs ;

  • Enfin, l'utilisation d'Assetic permet de garder votre confort de développement en local, vos fichiers ne sont ni regroupés, ni minifiés : indispensable pour déboguer !

Exemple de certificat de réussite
Exemple de certificat de réussite