Rails 4: les actifs ne se chargent pas en production

116

J'essaie de mettre mon application en production et les chemins des ressources image et css ne fonctionnent pas.

Voici ce que je fais actuellement:

  • Les éléments d'image se trouvent dans /app/assets/images/image.jpg
  • Les feuilles de style se trouvent dans /app/assets/stylesheets/style.css
  • Dans ma mise en page, je référence le fichier css comme ceci: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Avant de redémarrer unicorn, je cours RAILS_ENV=production bundle exec rake assets:precompileet ça réussit et je vois les fichiers d'empreintes digitales dans le public/assetsrépertoire.

Lorsque je navigue sur mon site, j'obtiens une erreur 404 non trouvée pour mysite.com/stylesheets/styles.css.

Qu'est-ce que je fais mal?

Mise à jour: Dans ma mise en page, cela ressemble à ceci:

<%= stylesheet_link_tag    "bootstrap.min", media: "all", "data-turbolinks-track" => true %>
<%= stylesheet_link_tag    "styles", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>

La source de génération est la suivante:

<link data-turbolinks-track="true" href="/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/stylesheets/styles.css" media="all" rel="stylesheet" />
<script data-turbolinks-track="true" src="/assets/application-0c647c942c6eff10ad92f1f2b0c64efe.js"></script>

Il semble que Rails ne recherche pas correctement les fichiers css compilés. Mais il est très déroutant de savoir pourquoi cela fonctionne correctement pour les javascripts (notez le /assets/****.jschemin).

emersonthis
la source
Pouvez-vous nous dire comment vous chargez votre fichier css? Il semble d'après votre erreur que vous essayez de le lier en dur plutôt que d'utiliser stylesheet_link_tag.
kik le
1
Juste ajouté ci-dessus. Je fais<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>
emersonthis
Ok, donc je recommanderais deux choses: 1. vérifier la source générée si cette ligne est écrite comme chemin vers public/assetset 2. vérifier s'il n'y a pas une autre instruction quelque part essayant de charger ce fichier css (vraisemblablement codé en dur)
kik
Je ne peux pas dire si l'utilisation de .erb est un problème car je ne le fais jamais: .home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }peut en fait être remplacé dans sprocket par .home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }. Peut-être que vous pouvez essayer si cela vous aide.
kik le
Êtes-vous en train de dire que je peux rendre cette référence dynamique dans mon fichier css sans ajouter l'extension .erb? Je l'ai changé parce que je ne voulais pas que le lien se rompe lorsque je suis en mode développement.
emersonthis

Réponses:

105

Dans les rails 4, vous devez effectuer les modifications ci-dessous:

config.assets.compile = true
config.assets.precompile =  ['*.js', '*.css', '*.css.erb'] 

Cela fonctionne avec moi. utiliser la commande suivante pour précompiler les ressources

RAILS_ENV=production bundle exec rake assets:precompile

Bonne chance!

Rameshwar Vyevhare
la source
11
Je pensais que définir config.assets.compile sur true tuerait les performances en production. aussi, css.erb? qui utilise ça? et qu'en est-il du sass et du café?
ahnbizcad
lorsque des fichiers coffee et sass sont demandés, ils sont traités par les processeurs fournis par les gemmes coffee-script et sass-rails, puis renvoyés au navigateur en tant que JavaScript et CSS respectivement.
Rameshwar Vyevhare
1
Ce problème est déjà résolu pour Rails 4 et donc pas besoin d'utiliser la gemme turbo-sprocket-rails3
Rameshwar Vyevhare
4
Désolé, je ne suis pas en mesure de faire le lien avec ce que vous avez dit pour répondre à ma question.
ahnbizcad
1
Normalement, lorsque vous exécutez un serveur de production, vous exécutez Rails avec passager, licorne ou puma derrière le serveur Web Apache ou nginx. Il est préférable de laisser Apache ou nginx servir des fichiers statiques (js, css, images) et le serveur d'applications Rails (puma, unicorn) servir le code et le modèle Rails. Pour ce faire, vous devez désactiver config.serve_static_fileset configurer l'alias dans Apache et nginx pour gérer assets.
Châu Hồng Lĩnh
85

J'ai juste eu le même problème et j'ai trouvé ce paramètre dans config / environnements / production.rb:

# Rails 4:
config.serve_static_assets = false

# Or for Rails 5:
config.public_file_server.enabled = false

Changer pour le truefaire fonctionner. Il semble que, par défaut, Rails s'attende à ce que vous ayez configuré votre serveur Web frontal pour gérer les demandes de fichiers hors du dossier public au lieu de les envoyer par proxy à l'application Rails. Peut-être avez-vous fait cela pour vos fichiers javascript mais pas vos feuilles de style CSS?

( Voir la documentation Rails 5 ). Comme indiqué dans les commentaires, avec Rails 5, vous pouvez simplement définir la RAILS_SERVE_STATIC_FILESvariable d'environnement, car le paramètre par défaut est config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.

Davmac
la source
1
AVERTISSEMENT DE DÉPRÉCIATION: L'option de configuration config.serve_static_assetsa été renommée pour config.serve_static_filesclarifier son rôle (elle permet simplement de servir tout ce qui se trouve dans le publicdossier et n'est pas liée au pipeline d'actifs). L' serve_static_assetsalias sera supprimé dans Rails 5.0. Veuillez migrer vos fichiers de configuration en conséquence.
yekta
Plus tôt, lorsque je faisais face à ce problème, changer cette ligne l'avait résolu pour moi, mais maintenant je le fais à nouveau (je ne sais pas comment je continue à me retrouver dans ces situations.) Et ce n'est pas suffisant. Avez-vous d'autres suggestions sur ce qui pourrait ne pas aller?
IIllIIll
2
Cela devrait être la réponse acceptée. Bien que ce soit config.serve_static_filesdans Rails 4.2 et config.public_file_server.enableddans Rails 5 . @see github.com/heroku/rails_serve_static_assets/blob/master/lib/…
Lucas Nelson
3
Le fichier config / environnements / production.rb de Rails 5.0.0.1 contient config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?afin que vous puissiez le définir différemment pour votre environnement sans changer le code qui est archivé dans votre SCM.
tobinjim
Pour l'activer: "export RAILS_SERVE_STATIC_FILES =" puis vous lancez "rails s -e production" Pour le désactiver: "unset RAILS_SERVE_STATIC_FILES"
Alfredo Osorio
32

Dans /config/environments/production.rbj'ai dû ajouter ceci:

Rails.application.config.assets.precompile += %w( *.js ^[^_]*.css *.css.erb )

Le .js était déjà précompilé, mais je l'ai quand même ajouté. Les .css et .css.erb ne se produisent apparemment pas automatiquement. Le ^[^_]exclut les partiels de la compilation - c'est une expression rationnelle.

Il est un peu frustrant que la documentation indique clairement que le pipeline d'actifs est activé par défaut, mais ne clarifie pas le fait que cela ne s'applique qu'aux javascripts.

emersonthis
la source
Vous devez ajouter styles.css à config.assets.precompile
Frederick Cheung
23

Je suis en mesure de résoudre ce problème en changeant: config.assets.compile = falseà
config.assets.compile = trueen/config/environments/production.rb

Mise à jour (24 juin 2018) : Cette méthode crée une vulnérabilité de sécurité si la version de Sprockets que vous utilisez est inférieure à 2.12.5, 3.7.2 ou 4.0.0.beta8

Yanofsky
la source
7
Cela ne signifie-t-il pas que Rails compile les actifs au lieu, par exemple, de les charger à partir d'un CDN?
Benjamin Oakes
@BenjaminOakes Oui, et c'est ce que je voulais
Yanofsky
2
Ce mode utilise plus de mémoire, fonctionne moins bien que la valeur par défaut et n'est pas recommandé. Mieux vaut utiliser un proxy nginx.
yekta
16

Pour Rails 5, vous devez activer le code de configuration suivant:

config.public_file_server.enabled = true

Par défaut, Rails 5 est livré avec cette ligne de configuration:

config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

Par conséquent, vous devrez définir la variable d'environnement RAILS_SERVE_STATIC_FILESsur true.

Ytbryan
la source
1
Pour Rails 5, je devrais ajouter, j'ai défini passenger_env_var RAILS_SERVE_STATIC_FILES true;le bloc d'emplacement de mon application dans mon fichier nginx.conf.
Martin Velez
10

Il y a 2 choses que vous devez accomplir pour servir les actifs en production:

  1. Précompilez les actifs.
  2. Servir les actifs sur le serveur au navigateur.

1) Afin de précompiler les actifs, vous avez plusieurs choix.

  • Vous pouvez l'exécuter rake assets:precompilesur votre machine locale, la valider dans le contrôle du code source (git), puis exécuter le programme de déploiement, par exemple capistrano. Ce n'est pas un bon moyen de valider des actifs précompilés dans SCM.

  • Vous pouvez écrire une tâche de râteau qui s'exécute RAILS_ENV=production rake assets:precompilesur les serveurs cibles chaque fois que vous déployez votre application Rails en production, avant de redémarrer le serveur.

Le code d'une tâche pour capistrano ressemblera à ceci:

on roles(:app) do
  if DEPLOY_ENV == 'production'
    execute("cd #{DEPLOY_TO_DIR}/current && RAILS_ENV=production rvm #{ruby_string} do rake assets:precompile")
  end
end

2) Maintenant, vous avez les actifs sur les serveurs de production, vous devez les servir au navigateur.

Encore une fois, vous avez plusieurs choix.

  • Activer le service de fichiers statiques Rails dans config / environnements / production.rb

    config.serve_static_assets = true # old
    
    or
    
    config.serve_static_files = true # new

    L'utilisation de Rails pour servir des fichiers statiques va tuer les performances de votre application Rails.

  • Configurez nginx (ou Apache) pour servir les fichiers statiques.

    Par exemple, mon nginx qui a été configuré pour fonctionner avec Puma ressemble à ceci:

    location ~ ^/(assets|images|fonts)/(.*)$ {
        alias /var/www/foster_care/current/public/$1/$2;
        gzip on;
        expires max;
        add_header Cache-Control public;
    }
Châu Hồng Lĩnh
la source
4

Rails 4 ne génère plus la version non empreinte digitale de l'élément: les feuilles de style / style.css ne seront pas générées pour vous.

Si vous utilisez, stylesheet_link_tagle lien correct vers votre feuille de style sera généré

De plus styles.cssdevrait être dans config.assets.precompilelaquelle se trouve la liste des choses qui sont précompilées

Frederick Cheung
la source
Je vois le fichier d'empreintes digitales dans le répertoire / public / assets /. Dans ma mise en page, j'ai ceci: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>Est-ce incorrect? ``
emersonthis
Pour une raison quelconque, le déploiement de production pointe toujours vers les fichiers d'origine lorsque je visualise la source <link data-turbolinks-track="true" href="https://stackoverflow.com/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />Mais les fichiers javascript sont corrects! Je ne comprends pas pourquoi les mêmes configurations fonctionnent pour les fichiers .js mais pas pour .css.
emersonthis
Sur Rails 5.0.0.beta3, j'obtiens cet avertissement: AVERTISSEMENT DE DÉPRÉCIATION: serve_static_filesest obsolète et sera supprimé dans Rails 5.1. Veuillez utiliser à la public_file_server.enabled = trueplace.
GMA
@emersonthis Même chose! Js se charge parfaitement mais certains fichiers css obtiennent 404. Avez-vous résolu ce problème?
IvRRimUm
C'est presque TOUJOURS un problème avec la configuration du pipeline d'actifs. Si vous avez des fichiers dans un emplacement qui n'est pas par défaut, c'est presque définitivement le problème et vous devez en informer le pipeline d'actifs en utilisant quelque chose comme la première réponse.
emersonthis
3

changer votre ligne de fichier Production.rb

config.assets.compile = false

dans

config.assets.compile = true

et aussi ajouter

config.assets.precompile =  ['*.js', '*.css', '*.css.erb']
Jassa Mahal
la source
pourquoi compiler? nous ne supposons pas de compiler en production pendant son exécution
James Tan
1
NE JAMAIS FAIRE CELA! Quiconque définit config.assets.compile sur true en production doit être abattu.
bkunzi01
2

J'utilise Ubuntu Server 14.04 , Ruby 2.2.1 et Rails 4.2.4 J'ai suivi un déploiement turorial de DigitalOcean et tout s'est bien passé mais quand je vais dans le navigateur et entre l'adresse IP de mon VPS mon application est chargée mais sans styles et javascript.

L'application fonctionne avec Unicorn et Nginx . Pour résoudre ce problème, je suis entré dans mon serveur en utilisant SSH avec mon utilisateur `` deployer '' et accédez au chemin de mon application qui est `` / home / deployer / apps / blog '' et exécutez la commande suivante:

RAILS_ENV=production bin/rake assets:precompile

Ensuite, je viens de redémarrer le VPS et c'est tout! Ça marche pour moi!

J'espère que cela pourrait être utile pour quelqu'un d'autre!

alexventuraio
la source
2

Si la précompilation est définie, vous n'avez PAS besoin

config.assets.compile = true

car il s'agit de servir les actifs en direct.

Notre problème était que nous n'avions qu'une base de clé secrète de développement définie dans config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

Besoin d'entrée pour l'environnement de production

xxjjnn
la source
1
comme mentionné dans d'autres réponses dont vous avez besoin config.assets.precompile = ['*.js', '*.css', '*.css.erb'] et à exécuterRAILS_ENV=production bundle exec rake assets:precompile
xxjjnn
1
cela permet la compilation d'actifs en direct sur la production, très lent, pas bien
James Tan
2

CE QUE VOUS NE DEVRIEZ PAS faire:

Certains de mes collègues ci-dessus vous ont recommandé de faire ceci:

config.serve_static_assets = true  ## DON”T DO THIS!! 
config.public_file_server.enabled = true ## DON”T DO THIS!!

Le pipeline d'actifs ferroviaires dit de l'approche ci-dessus:

Ce mode utilise plus de mémoire, fonctionne moins bien que la valeur par défaut et n'est pas recommandé. Voir ici: ( http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation )

Ce que tu devrais faire:

Précompilez vos actifs.

RAILS_ENV=production rake assets:precompile

Vous pouvez probablement le faire avec une tâche de râteau.

BKSpurgeon
la source
Pourquoi ajouter des artefacts de construction au git? Vous pouvez simplement ajouter une tâche de rake à votre processus de construction et éviter un gitspam massif (surtout si vous avez uglifier et gzipping, ce que vous devriez)
Dr.Strangelove
@ Dr.Strangelove Merci pour votre commentaire - je n'en sais pas assez à ce sujet -: pouvez-vous élaborer / éditer le message original?
BKSpurgeon
1

Le matcher par défaut pour la compilation de fichiers comprend application.js, application.css et tous les fichiers non-JS / CSS (cela inclura automatiquement tous les actifs d'image) à partir des dossiers app / assets, y compris vos gemmes:

Si vous avez d'autres manifestes ou feuilles de style individuelles et fichiers JavaScript à inclure, vous pouvez les ajouter au tableau de précompilation dans config / initializers / assets.rb:

Rails.application.config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js']

http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets

FreePender
la source
1

Tout d'abord, vérifiez vos actifs, il est possible qu'il y ait une erreur lors de la pré-compilation des actifs.

Pour précompiler les actifs en production ENV, exécutez cette commande:

RAILS_ENV=production rake assets:precompile

S'il affiche une erreur, supprimez-la d'abord,

En cas d'erreur "variable non définie", chargez ce fichier de variable avant de l'utiliser dans un autre fichier.

exemple:

@import "variables";
@import "style";

dans le fichier application.rb, séquence de la pré-compilation des actifs

exemple:

config.assets.precompile += [ 'application.js', 'admin.js', 'admin/events.js', 'admin/gallery.js', 'frontendgallery.js']

config.assets.precompile += [ 'application.css', 'admin.css','admin/events.css', 'admin/gallery.css', 'frontendgallery.css']
Chitresh goyal
la source
1

Trouvé ceci:

L'option de configuration config.serve_static_assetsa été renommée enconfig.serve_static_files pour clarifier son rôle.

dans config/environments/production.rb:

# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?

Alors définissez env RAILS_SERVE_STATIC_FILESou using Nginxpour servir des fichiers statiques. L'ajout config.serve_static_assets = truefonctionnera toujours, mais supprimé à l'avenir.

Daniel Wei
la source
1

il n'est pas recommandé de laisser capistrano effectuer la précompilation des assets, car cela peut prendre des années et souvent du temps. essayez de faire une précompilation des actifs locaux.

Tout d'abord, définissez dans config / application.rb config.assets.initialize_on_precompile = false puis faites local RAILS_ENV=production bin/rake assets:precompile et ajoutez ces public / assets à git.

et config / environnements / development.rb, modifiez le chemin de votre actif pour éviter d'utiliser des actifs précompilés:

config.assets.prefix = '/dev-assets'

Si vous avez un problème de connexion db, cela signifie que vous avez un initialiseur qui utilise db. une façon de contourner le problème est de définir un nouvel environnement en dupliquant production.rb comme peut-être production2 .rb, et dans database.yml, ajouter l' environnement production2 avec le paramètre de base de données de développement . alors fais

RAILS_ENV=production2 bin/rake assets:precompile

si vous rencontrez toujours un problème avec les actifs, par exemple ckeditor, ajoutez le fichier js dans config / initializers / assets.rb

Rails.application.config.assets.precompile += %w( ckeditor.js )

James Tan
la source
0

Je me trompe peut-être mais ceux qui recommandent de changer

config.assets.compile = true

Le commentaire sur cette ligne se lit comme suit: # Ne pas revenir au pipeline d'actifs si un actif précompilé est manqué.

Cela suggère qu'en définissant ceci sur true, vous ne résolvez pas le problème, mais vous le contournez et exécutez le pipeline à chaque fois. Cela doit sûrement tuer vos performances et faire échouer l'objectif du pipeline?

J'ai eu cette même erreur et c'était dû au fait que l'application fonctionnait dans un sous-dossier que les rails ne connaissaient pas.

Donc, mon fichier css était dans home / sous-dossier / app / public / .... mais rails cherchait dans home / app / public / ...

essayez de déplacer votre application hors du sous-dossier ou d'indiquer aux rails qu'elle se trouve dans un sous-dossier.

Brad
la source
0
location ~ ^/assets/ {
  expires 1y;
  add_header Cache-Control public;
  add_header ETag "";
}

Cela a résolu le problème pour moi en production. Mettez-le dans la configuration nginx.

Pedro Adame Vergara
la source
0

Même nous avons été confrontés au même problème lorsque nous avons RAILS_ENV=production bundle exec rake assets:precompileréussi, mais les choses n'ont pas fonctionné comme prévu.
Nous avons découvert que la licorne était le principal coupable ici.

Comme dans votre cas, même nous avions l'habitude de redémarrer unicorn après avoir compilé les actifs. On a remarqué que lorsque la licorne est redémarrée, seuls ses processus de travail sont redémarrés et non le processus maître.
C'est la raison principale pour laquelle les bons actifs ne sont pas servis.

Plus tard, après avoir compilé les actifs, nous avons arrêté et démarré unicorn afin que le processus maître licorne soit également redémarré et que les actifs corrects soient servis.
L'arrêt et le démarrage de la licorne impliquent environ 10 secondes de temps d'arrêt par rapport au redémarrage de la licorne. C'est la solution de contournement qui peut être utilisée lorsqu'une solution à long terme est de passer au puma de la licorne.

Bhavya Keniya
la source