config.assets.compile = true dans la production Rails, pourquoi pas?

185

L'application Rails par défaut installée par rails newest config.assets.compile = falseen production.

Et la façon habituelle de faire les choses consiste à exécuter rake assets:precompileavant de déployer votre application, pour vous assurer que tous les actifs du pipeline d'actifs sont compilés.

Alors que se passe-t-il si je mets config.assets.compile = trueen production?

Je n'ai plus besoin de courir precompile. Ce que je crois arriver, c'est la première fois qu'un actif est demandé, il sera compilé. Ce sera un coup de performance la première fois (et cela signifie que vous avez généralement besoin d'un runtime js en production pour le faire). Mais à part ces inconvénients, une fois l'actif compilé paresseusement, je pense que tous les accès ultérieurs à cet actif n'auront aucun impact sur les performances, les performances de l'application seront exactement les mêmes que celles des actifs précompilés après cette première compilation paresseuse de premier succès. Est-ce vrai?

Y a-t-il quelque chose qui me manque? Y a-t-il d'autres raisons de ne pas mettre config.assets.compile = trueen production? Si j'ai un runtime JS en production et que je suis prêt à accepter le compromis de performances dégradées pour le premier accès d'un actif, en échange de ne pas avoir à s'exécuter precompile, est-ce que cela a du sens?

jrochkind
la source
1
Attention, les anciennes versions de sprockets contiennent un bogue et si config.assets.compile est configuré sur true, il existe un risque de vulnérabilité de trasversal de répertoire ( blog.heroku.com/rails-asset-pipeline-vulnerability )
Mauro
C'est exactement ainsi que Stackoverflow est censé fonctionner. Une question bien écrite et une réponse bien écrite. Je vous aime tous les deux op et @ richard-hulse.
schmijos

Réponses:

259

J'ai écrit cette partie du guide.

Vous ne voulez certainement pas vivre la compilation en production.

Lorsque vous avez compilé, voici ce qui se passe:

Chaque demande de fichier dans / assets est transmise à Sprockets. Lors de la première requête pour chaque actif, il est compilé et mis en cache dans tout ce que Rails utilise pour le cache (généralement le système de fichiers).

Lors des demandes suivantes, Sprockets reçoit la demande et doit rechercher le nom du fichier d'empreintes digitales, vérifier que le fichier (image) ou les fichiers (css et js) qui composent l'actif n'ont pas été modifiés, puis s'il existe une version mise en cache.

C'est tout ce qui se trouve dans le dossier des actifs et dans tous les dossiers de fournisseur / actifs utilisés par les plugins.

C'est beaucoup de frais généraux car, pour être honnête, le code n'est pas optimisé pour la vitesse.

Cela aura un impact sur la rapidité avec laquelle l'actif sera transmis au client et aura un impact négatif sur les temps de chargement des pages de votre site.

Comparez avec la valeur par défaut:

Lorsque les ressources sont précompilées et que la compilation est désactivée, les ressources sont compilées et empreintes dans le fichier public/assets. Sprockets renvoie une table de mappage des noms de fichiers simples aux empreintes digitales vers Rails, et Rails l'écrit dans le système de fichiers. Le fichier manifeste (YML dans Rails 3 ou JSON avec un nom aléatoire dans Rails 4) est chargé dans la mémoire par Rails au démarrage et mis en cache pour être utilisé par les méthodes d'assistance des ressources.

Cela rend la génération de pages avec les actifs d'empreintes digitales correctes très rapide, et le service des fichiers eux-mêmes est rapide du serveur Web à partir du système de fichiers. Les deux sont considérablement plus rapides que la compilation en direct.

Pour tirer le meilleur parti du pipeline et de l'empreinte digitale, vous devez définir des en-têtes pour l'avenir lointain sur votre serveur Web et activer la compression gzip pour les fichiers js et css. Sprockets écrit des versions gzippées d'actifs que vous pouvez configurer votre serveur pour qu'il utilise, ce qui lui évite d'avoir à le faire pour chaque requête.

Cela permet de transmettre les actifs au client le plus rapidement possible et dans la plus petite taille possible, ce qui accélère l'affichage des pages côté client et réduit les demandes (avec un en-tête pour un futur lointain).

Donc, si vous compilez en direct, c'est:

  1. Très lent
  2. Manque de compression
  3. Cela aura un impact sur le temps de rendu des pages

Contre

  1. Aussi vite que possible
  2. Comprimé
  3. Supprimez la compression entendue du serveur (facultatif).
  4. Réduisez le temps de rendu des pages.

Edit: (Réponse au commentaire de suivi)

Le pipeline pourrait être modifié pour être précompilé à la première demande, mais il existe des obstacles majeurs à le faire. La première est qu'il doit y avoir une table de recherche pour les noms d'empreintes digitales ou les méthodes d'aide sont trop lentes. Dans le cadre d'un sénario de compilation à la demande, il devrait y avoir un moyen d'ajouter à la table de recherche à mesure que chaque nouvel actif est compilé ou demandé.

En outre, quelqu'un devrait payer le prix d'une livraison lente des actifs pendant une période de temps inconnue jusqu'à ce que tous les actifs soient compilés et en place.

La valeur par défaut, où le prix de la compilation de tout est payé hors ligne en une seule fois, n'a pas d'impact sur les visiteurs publics et garantit que tout fonctionne avant la mise en ligne.

Le problème, c'est que cela ajoute beaucoup de complexité aux systèmes de production.

[Edit, juin 2015] Si vous lisez ceci parce que vous recherchez une solution pour les temps de compilation lents pendant un déploiement, vous pouvez envisager de précompiler les actifs localement. Des informations à ce sujet se trouvent dans le guide du pipeline d'actifs . Cela vous permet de précompiler localement uniquement lorsqu'il y a un changement, de le valider, puis d'avoir un déploiement rapide sans étape de précompilation.

Richard Hulse
la source
1
Merci, j'ai accepté votre réponse. Mais maintenant ma question est, d'accord, il ne le fait pas maintenant, mais pensez-vous que le pipeline d'actifs pourrait avoir une fonctionnalité où il se compile paresseusement à la première demande, le faisant exactement comme une précompilation, y compris l'écriture dans ./public et la mise à jour le manifeste des empreintes digitales?
jrochkind
Voir au dessus. Est-ce un problème parce que Capistrano ne fonctionne pas pour vous?
Richard Hulse
Je n'utilise pas Capistrano. Je n'en ai pas eu besoin avant, la complexité supplémentaire n'en valait pas la peine. Peut-être que le pipeline d'actifs est la paille qui brise les chameaux et en a besoin. À votre avis, il est impossible de gérer les déploiements de Rails avec un pipeline d'actifs sans capistrano ou similaire? C'est dommage, pour les configurations simples, ce n'était pas un gros problème de le faire à la main.
jrochkind
Vous avez vraiment besoin de Capistrano pour Rails 3.1. Les actifs sont compilés dans un nouveau répertoire public pendant que votre ancienne application est toujours en cours d'exécution. Lorsque la compilation est terminée, la nouvelle version est liée par un lien symbolique et le serveur redémarre automatiquement.
Richard Hulse
"Pour tirer le meilleur parti du pipeline et des empreintes digitales, vous devez définir des en-têtes pour l'avenir lointain sur votre serveur Web et activer la compression gzip pour les fichiers js et css." - Pourriez-vous s'il vous plaît fournir des instructions ou des liens pour savoir comment faire ce?
Isaac Betesh
7

Pour avoir moins de frais généraux avec la pré-compilation.

Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/

vous pouvez alors simplement utiliser des images et des feuilles de style comme "/assets/stylesheet.css" dans * .html.erb ou "/assets/web.png"

dbKooper
la source
6

Pour toute personne utilisant Heroku:

Si vous déployez sur Herkou, il effectuera la précompilation pour vous automatiquement pendant le déploiement si les actifs compilés ne sont pas inclus (c'est-à-dire public/assetsnon validés) donc pas besoin de config.assets.compile = true, ou de valider les actifs précompilés.

Les documents d'Heroku sont ici . Un CDN est recommandé pour supprimer la charge sur la ressource dyno.

William Denniss
la source
1

Ce ne sera pas la même chose que la précompilation, même après ce premier coup: parce que les fichiers ne sont pas écrits sur le système de fichiers, ils ne peuvent pas être servis directement par le serveur Web. Un certain code ruby ​​sera toujours impliqué, même s'il lit simplement une entrée de cache.

Frederick Cheung
la source
Hmm, je pensais qu'avec precompile=true, les actifs compilés seraient écrits dans le système de fichiers. Êtes-vous sûr? Laissez-moi vérifier ...
jrochkind
1
Bah, je pense que vous avez raison - ils SONT écrits dans le système de fichiers, mais cela ressemble à tmp/cacheplutôt qu'à public/assets, donc pas un endroit que le serveur Web peut voir, ils vont toujours être desservis par l'application rails non le serveur Web. blabla. est-ce vrai, vous pensez?
jrochkind
Correct. Ce ne sera pas aussi rapide que de les récupérer directement par le serveur Web. Peu importe si vous mettez un cdn comme cloudfront devant votre application
Frederick Cheung
1

Ensemble config.asset.compile = false

Ajouter à votre Gemfile

group :assets do gem 'turbo-sprockets-rails3' end

Installez le bundle

Courir rake assets:precompile

Puis démarrez votre serveur

Mohammed Saleem
la source
Dans la mesure où j'ai défini le config.asset.compile = true in production.rbfichier, car il n'y a pas de mécanisme de pré-exécution ajouté. En raison de cela, chaque fois que nous démarrons le serveur, le chargement de la page prend trop de temps (lorsque la requête atteint à la fois le traitement de la requête et la compilation des actifs). Maintenant, j'ai inclus turbo-sprockets-rails3dans Gemfile et exécutez la commande rake assets:precompilepour compiler les actifs au préalable. Maintenant, je configure config.asset.compile = false in production.rbet démarre le serveur, la page se charge sans délai. (Traitement de la demande uniquement sans compilation d'actifs)
Mohammed Saleem
2
cela vaut la peine de dire que ce turbo-sprockets-rails3n'est nécessaire que sur Ruby 3
Andre Figueiredo
0

Du guide officiel :

À la première demande, les actifs sont compilés et mis en cache comme indiqué dans le développement ci-dessus, et les noms de manifeste utilisés dans les helpers sont modifiés pour inclure le hachage MD5.

Sprockets définit également l'en-tête HTTP Cache-Control sur max-age = 31536000. Cela signale à tous les caches entre votre serveur et le navigateur client que ce contenu (le fichier servi) peut être mis en cache pendant 1 an. Cela a pour effet de réduire le nombre de requêtes pour cet actif de votre serveur; l'actif a de bonnes chances d'être dans le cache du navigateur local ou dans un cache intermédiaire.

Ce mode utilise plus de mémoire, fonctionne moins bien que la valeur par défaut et n'est pas recommandé.

De plus, l'étape de précompilation n'est pas du tout un problème si vous utilisez Capistrano pour vos déploiements. Il s'en occupe pour vous. Vous venez de courir

cap deploy

ou (selon votre configuration)

cap production deploy

et vous êtes prêt. Si vous ne l'utilisez toujours pas, je vous recommande vivement de le vérifier.

Sergio Tulentsev
la source
Alors, pensez-vous que la langue du guide officiel est d'accord avec moi? J'ai vu ce guide, je ne sais pas si cela signifie ce que je suggère ci-dessus, qu'en pensez-vous? Voilà ma question.
jrochkind
Oui, vous dites fondamentalement la même chose. Je vous suggère de ne pas activer la compilation en direct.
Sergio Tulentsev