#279 Understanding the Asset Pipeline
- Download:
- source codeProject Files in Zip (438 KB)
- mp4Full Size H.264 Video (24.8 MB)
- m4vSmaller H.264 Video (13.5 MB)
- webmFull Size VP8 Video (17.5 MB)
- ogvFull Size Theora Video (28.5 MB)
L'asset pipeline est une des plus importantes fonctionnalités de Rails 3.1. Elle peut cependant être difficile à appréhender. Dans cet épisode, nous allons tenter de la démystifier un peu en montrant comment elle gère les ressources media (assets) de vos applications Rails. Si le sujet vous est totalement inconnu, un bon point de départ est le Guide Rails sur l'asset pipeline qui aborde bon nombre de ses fonctionnalités.
Si vous avez écrit une application Rails 3.1, vous savez probablement qu'en visitant http://localhost:3000/assets/application.js
, vous allez obtenir un fichier contenant tous les fichiers JavaScript de votre application. Mais comment cela fonctionne-t-il ?
Le fichier application.js
n'a rien de particulier. Tout fichier placé dans le dossier /app/assets/javascripts
est tout autant accessible. Si, par exemple, nous créons, dans ce dossier, un fichier nommé greeting.txt
, nous pouvons le voir dans le navigateur en visitant http://localhost:3000/assets/greeting.txt
. Bien que le fichier soit dans /app/assets/javascripts
, l'URL par laquelle nous y accédons est /assets/greeting.txt
. Cela s'applique, peu importe, dans quel sous dossier de /app/assets
nous plaçons le fichier. Nous pouvons même créer un nouveau dossier et y placer le fichier, il sera toujours accessible à la même URL. Si nous créons effectivement un nouveau dossier, nous devrons tout de même relancer le serveur avant que les fichiers que l'on y place soient accessibles.
Le dossier /app/assets
n'est pas le seul dans lequel nous pouvons ajouter des assets. Si nous créons un dossier assets
dans /lib
, tout fichier placé dans celui-ci sera accessible comme s'il était mis dans le dossier /app/assets
. Cela s'applique également à tout fichier placé dans le dossier /vendor/assets
.
Si vous avez des assets qui ne sont pas vraiment spécifiques à l'application courante, les dossiers assets
situés dans /lib
ou /vendor
sont leur destination idéale. Si l'application utilise un plugin jQuery, le dossier /vendor/assets
est l'endroit où placer ses fichiers JavaScript puisqu'ils sont maintenus par quelqu'un d'autre. Pour les assets maintenus par nos soins mais qui ne sont pas spécifiques à l'application, le choix se portera plutôt sur le dossier /lib
.
Dans sa forme la plus basique, l'asset pipeline est une liste de chemins de chargement (loadpaths). Nous pouvons voir cette liste en lançant la console Rails et en inspectant Rails.application.config.assets.paths
. Nous afficherons le résultat en YAML pour plus de lisibilité.
> y Rails.application.config.assets.paths --- - /Users/eifion/store/app/assets/images - /Users/eifion/store/app/assets/javascripts - /Users/eifion/store/app/assets/stylesheets - /Users/eifion/store/lib/assets/greeting.txt - /Users/eifion/store/vendor/assets/stylesheets - /Users/eifion/.rvm/gems/ruby-1.9.2-p180@railspre/gems/jquery-rails-1.0.13/vendor/assets/javascripts
Le résultat est une liste de tous les dossiers contenus dans /app/assets
ainsi que ceux présents dans /lib/assets
et /vendor/assets
. On trouve toutefois un dossier intéressant à la fin de la liste. Celui-ci provient de la gem jquery-rails
, incluse dans notre application. Nous pouvons voir son contenu grâce à la commande bundle open
.
$ bundle open jquery-rails
Cela ouvre la gem avec l'éditeur définit dans les variables d'environnement BUNDLER_EDITOR
ou EDITOR
. Si nous jetons un œil aux fichiers de la gem, nous allons voir un dossier vendor/asset/javascripts
contenant un certain nombre de fichiers jQuery que nous pouvons charger via l'asset pipeline.
Comme vous pouvez vous y attendre, nous pouvons accéder à chacun de ces fichiers, via le navigateur, sous le chemin assets
puisque le dossier les contenant est listé dans le loadpath de l'asset pipeline.
Ce qu'il est intéressant de noter, c'est que cela signifie que les gems Ruby n'ont plus pour unique but de gérer du code Ruby. Nous pouvons les utiliser pour gérer des fichiers JavaScript ou tout autre type d'asset. Il est à parié que nous verrons, sous peu, de nombreuses librairies JavaScript distribuées sous forme de gems Ruby, nous pourrons alors profiter des avantages de Bundler et de sa gestion des dépendances.
Gérer les Assets avec Sprockets
Retournons au fichier application.js
de notre application et jetons-y un œil.
// This is a manifest file that'll be compiled into including all the files listed below. // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically // be included in the compiled file accessible from http://example.com/assets/application.js // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // the compiled file. // //= require jquery //= require jquery_ujs //= require_tree .
Le fichier contient uniquement des commentaires mais certains ont une signification. Ce type de fichier est un manifest et est géré par Sprockets. Lorsqu'une requête pour ce fichier arrive, Sprockets lit le manifest et compile tous les fichiers mentionnés dans celui-ci puis inclut leur contenu avant le code du manifest.
Le loadpath fonctionne également ici. Nous trouvons une ligne require jquery
dans ce fichier (l'extension .js
est facultative). Sprockets va chercher ce fichier dans le loadpath et, dans le cas de jquery, le charger depuis le dossier vendor/asset/javascripts
de l'engine jquery-rails
.
Nous pouvons ajouter n'importe quel fichier JavaScript se trouvant dans le loadpath. Si nous ajoutons require jquery-ui
au manifest, le fichier jquery-ui.js
sera inclus. Cela s'applique également aux fichiers CoffeeScript. Si nous ajoutons require home
, le fichier /app/assets/javascripts/home.js.coffee
va être analysé et inclus.
Inclure ce fichier home
n'est pas nécessaire car, en bas du fichier, on trouve require_tree .
. Le point représente ici le dossier courant. Cela signifie que tout fichier JavaScript ou CoffeeScript présent dans ce dossier et ses sous dossiers sera inclus.
Si nous voulons exclure certains fichiers de l'arborescence, nous le pouvons. Disons que nous avons des pages d'administration sur notre site et que certains fichiers JavaScript doivent être inclus uniquement sur ces pages. Par défaut, ces fichiers vont être inclus sur toutes les pages du site.
Si nous voulons voir les fichiers inclus, nous pouvons ajouter un paramètre debug_assets=1
à l'URL. Cela va stopper l'agrégation des fichiers JavaScript et, lorsque nous consultons le code source de la page, nous allons voir tous les fichiers que Sprockets inclurait, y compris les fichiers du dossier admin.
Il existe deux façons de résoudre ce problème. Nous pourrions utiliser require_directory
au lieu de require_tree
. Cela permettrait de charger uniquement les fichiers du dossier courant et non ceux de ses sous dossiers. Si nous voulions plus de contrôle sur les fichiers inclus, nous pourrions faire appel à require
sur chaque fichier plutôt que sur le dossier. Nous pourrions également déplacer les fichiers JavaScript que nous souhaitons inclure sur toutes les pages dans un sous dossier public
et utiliser require_tree ./public
pour inclure uniquement ces fichiers.
Si vous vous demandez quelles commandes peuvent être utilisées dans un manifest Sprockets, il n'existe pas encore de bonne documentation mais, dans le code source du fichier directive_processor.rb
, on peut trouver des commentaires expliquant comment tout cela fonctionne et quelles sont les commandes utilisables.
Prétraitement
L'asset pipeline permet également de faire du prétraitement. Pour montrer comment cela fonctionne, nous allons créer un fichier nommé greeting.txt
dans un nouveau dossier /app/assets/anything
. Tel quel, c'est simplement un fichier texte statique mais, nous pouvons ajouter une autre extension au nom de fichier et spécifier un processeur, par exemple .erb
. Nous pouvons maintenant ajouter du code ERB dans ce fichier et il sera traité.
hello world <%= 1 + 1 %>
Si nous regardons ce fichier dans un navigateur, nous allons voir que le code ERB a été exécuté. Notez que nous n'incluons pas l'extension du préprocesseur dans l'URL.
C'est essentiellement la manière de fonctionner de SASS et CoffeeScript. Lorsqu'un fichier a une extension .scss
, elle est traitée comme une extension de préprocesseur et le fichier passera par le processeur SASS. Nous pouvons même chaîner les extensions et créer un fichier avec, par exemple, une extension .scss.erb
. Ce fichier passerait d'abord par le processeur ERB puis par le processeur SASS.
Le prétraitement est très configurable. Nous pouvons ajouter notre propre processeur ou échanger ceux existants. Tout est géré par la gem Tilt.
Les différences en mode Production
C'est tout pour notre tour rapide de l'asset pipeline. Il existe quelques différences sur son fonctionnement en production et nous allons terminer cet épisode en les abordant. Tout d'abord, nous allons lancer notre serveur en mode production.
$ rails s -e production
Si nous visitons la page d'accueil de notre application et regardons son code source, nous allons voir que nos assets sont délivrés différemment.
<link href="/assets/application-412fe22651f4486c51e54176003a9f57.css" media="screen" rel="stylesheet" type="text/css" /> <script src="/assets/application-3e3a5167191afa70c7b72440eee7dd40.js" type="text/javascript"></script>
Les noms de fichiers incluent un hash prévu pour le cache. Cela fonctionne bien mieux que l'ancienne méthode, basée sur la query string et utilisée par Rails 3.0, car le nom des fichiers est modifié. Si nous regardons le contenu des fichiers, nous pouvons voir qu'il sont minifiés pour économiser de la bande passante.
Ces assets sont automatiquement mis en cache et servis par le middleware Rack Cache pour plus de rapidité. Si nous voulons que le serveur web se charge lui-même de servir et héberger ces assets, nous pouvons les précompiler en lançant
$ rake assets:precompile
Cela va précompiler les assets dans le dossier /public
pour les rendre facilement accessibles par le serveur web.
C'est tout pour cet épisode sur l'asset pipeline. N'oubliez pas de regarder le Guide Rails pour plus d'informations.