Rails 4: asset che non vengono caricati in produzione


116

Sto cercando di mettere la mia app in produzione e i percorsi delle risorse di immagine e CSS non funzionano.

Ecco cosa sto facendo attualmente:

  • Le risorse immagine risiedono in /app/assets/images/image.jpg
  • I fogli di stile sono disponibili in /app/assets/stylesheets/style.css
  • Nel mio layout, faccio riferimento al file css in questo modo: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Prima di riavviare Unicorn, corro RAILS_ENV=production bundle exec rake assets:precompilee riesce e vedo i file con le impronte digitali nella public/assetsdirectory.

Quando navigo nel mio sito, ricevo un errore 404 non trovato per mysite.com/stylesheets/styles.css.

Che cosa sto facendo di sbagliato?

Aggiornamento: nel mio layout, assomiglia a questo:

<%= 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 sorgente di generazione è questa:

<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>

Sembra che Rails non stia cercando correttamente i file css compilati. Ma è molto confuso il motivo per cui funziona correttamente per i javascript (notare il /assets/****.jspercorso).


Puoi dirci come carichi il tuo file css? Dal tuo errore sembra che tu provi a collegarlo come hardlink invece di usarlo stylesheet_link_tag.
kik

1
Appena aggiunto sopra. Sto facendo<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>
emersonthis

Ok, quindi consiglierei due cose: 1. controlla la sorgente generata se questa riga è scritta come percorso public/assetse 2. ricontrolla se non c'è un'altra istruzione da qualche parte che cerca di caricare quel file css (presumibilmente hard-coded)
kik

Non posso dire se l'utilizzo di .erb sia un problema perché non lo faccio mai: .home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }può effettivamente essere sostituito in sprocket con .home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }. Forse puoi provare se questo aiuta.
kik

Stai dicendo che posso rendere dinamico quel riferimento nel mio file css senza aggiungere l'estensione .erb? L'ho cambiato perché non volevo che il collegamento si interrompesse quando sono in modalità di sviluppo.
emersonthis

Risposte:


105

In rails 4 è necessario apportare le modifiche seguenti:

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

Questo funziona con me. utilizzare il seguente comando per precompilare le risorse

RAILS_ENV=production bundle exec rake assets:precompile

Buona fortuna!


11
Pensavo che impostare config.assets.compile su true avrebbe ucciso le prestazioni in produzione. inoltre, css.erb? chi lo usa? e che dire di sass e caffè?
ahnbizcad

quando vengono richiesti i file coffee e sass, vengono elaborati dai processori forniti dalle gemme coffee-script e sass-rails e quindi rimandati al browser come JavaScript e CSS rispettivamente.
Rameshwar Vyevhare

1
Questo problema è già stato risolto per Rails 4 e quindi non è necessario utilizzare turbo-sprocket-rails3 gem
Rameshwar Vyevhare

4
Mi spiace, non sono in grado di collegare ciò che hai detto per rispondere alla mia domanda.
ahnbizcad

1
Normalmente, quando esegui il server di produzione, eseguirai Rails con passeggero o unicorno o puma dietro il server web Apache o nginx. È meglio lasciare che Apache o nginx servano file statici (js, css, immagini) e che il server delle applicazioni Rails (puma, unicorn) serva codice e template Rails. Per fare ciò, dovresti disattivare config.serve_static_filese configurare l'alias in Apache e nginx da gestire assets.
Châu Hồng Lĩnh

85

Ho appena avuto lo stesso problema e ho trovato questa impostazione in config / environment / production.rb:

# Rails 4:
config.serve_static_assets = false

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

Cambiarlo per truefarlo funzionare. Sembra che per impostazione predefinita Rails si aspetti che tu abbia configurato il tuo server web front-end per gestire le richieste di file fuori dalla cartella pubblica invece di inviarli tramite proxy all'app Rails. Forse l'hai fatto per i tuoi file javascript ma non per i tuoi fogli di stile CSS?

( Vedi la documentazione di Rails 5 ). Come notato nei commenti, con Rails 5 puoi semplicemente impostare la RAILS_SERVE_STATIC_FILESvariabile d'ambiente, poiché l'impostazione predefinita è config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.


1
AVVISO DI DEPRECAZIONE: L'opzione di configurazione config.serve_static_assetsè stata rinominata per config.serve_static_fileschiarirne il ruolo (consente semplicemente di servire tutto nella publiccartella e non è correlata alla pipeline degli asset). L' serve_static_assetsalias verrà rimosso in Rails 5.0. Si prega di migrare i file di configurazione di conseguenza.
yekta

In precedenza, quando stavo affrontando questo problema, cambiare quella linea mi aveva risolto, ma ora lo sto affrontando di nuovo (non so come continuo a finire in queste situazioni) e questo non è abbastanza. Qualche altro suggerimento su cosa potrebbe essere sbagliato?
IIllIIll

2
Questa dovrebbe essere la risposta accettata. Sebbene sia config.serve_static_filesin Rails 4.2 e config.public_file_server.enabledin Rails 5 . @see github.com/heroku/rails_serve_static_assets/blob/master/lib/…
Lucas Nelson

3
Rails 5.0.0.1 config / environment / production.rb contiene in config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?modo che tu possa impostarlo in modo diverso per il tuo ambiente senza modificare il codice che è stato archiviato nel tuo SCM.
tobinjim

Per abilitarlo: "export RAILS_SERVE_STATIC_FILES =" quindi esegui "rails s -e production" Per disabilitarlo: "unset RAILS_SERVE_STATIC_FILES"
Alfredo Osorio

32

In /config/environments/production.rbho dovuto aggiungere questo:

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

Il .js veniva già precompilato, ma l'ho aggiunto comunque. I file .css e .css.erb apparentemente non vengono eseguiti automaticamente. Il ^[^_]parziale esclude dalla compilazione: è una regexp.

È un po 'frustrante che i documenti affermino chiaramente che la pipeline di risorse È abilitata per impostazione predefinita, ma non chiarisce il fatto che si applica solo ai javascript.


Devi aggiungere styles.css a config.assets.precompile
Frederick Cheung

23

Sono stato in grado di risolvere questo problema modificando: config.assets.compile = falsea
config.assets.compile = truein/config/environments/production.rb

Aggiornamento (24 giugno 2018) : questo metodo crea una vulnerabilità di sicurezza se la versione di Sprockets che stai utilizzando è inferiore a 2.12.5, 3.7.2 o 4.0.0.beta8


7
Questo non significa che Rails sta compilando gli asset invece di, diciamo, caricarli da un CDN?
Benjamin Oakes

@BenjaminOakes Sì, ed è quello che volevo
Yanofsky

2
Questa modalità utilizza più memoria, ha prestazioni inferiori rispetto a quella predefinita e non è consigliata. Meglio usare un proxy nginx.
yekta

16

Per Rails 5, dovresti abilitare il seguente codice di configurazione:

config.public_file_server.enabled = true

Per impostazione predefinita, Rails 5 viene fornito con questa linea di configurazione:

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

Quindi, sarà necessario impostare la variabile di ambiente RAILS_SERVE_STATIC_FILESsu true.


1
Per Rails 5, dovrei aggiungere, ho impostato passenger_env_var RAILS_SERVE_STATIC_FILES true;nel blocco della posizione della mia app nel mio file nginx.conf.
Martin Velez

10

Ci sono 2 cose che devi compiere per servire le risorse in produzione:

  1. Precompilare gli asset.
  2. Offri le risorse sul server al browser.

1) Per precompilare le risorse, hai diverse scelte.

  • È possibile eseguire rake assets:precompilesulla macchina locale, eseguire il commit nel controllo del codice sorgente (git), quindi eseguire il programma di distribuzione, ad esempio capistrano. Questo non è un buon modo per eseguire il commit degli asset precompilati in SCM.

  • Puoi scrivere un'attività rake che viene eseguita RAILS_ENV=production rake assets:precompilesui server di destinazione ogni volta che distribuisci la tua app Rails in produzione, prima di riavviare il server.

Il codice in un'attività per capistrano sarà simile a questo:

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) Ora, hai le risorse sui server di produzione, devi servirle al browser.

Ancora una volta, hai diverse scelte.

  • Attiva il file serving statico di Rails in config / environment / production.rb

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

    Usare Rails per servire file statici ucciderà le prestazioni della tua app Rails.

  • Configura nginx (o Apache) per servire file statici.

    Ad esempio, il mio nginx che è stato configurato per funzionare con Puma ha questo aspetto:

    location ~ ^/(assets|images|fonts)/(.*)$ {
        alias /var/www/foster_care/current/public/$1/$2;
        gzip on;
        expires max;
        add_header Cache-Control public;
    }

4

Rails 4 non genera più la versione senza impronte digitali dell'asset: stylesheets / style.css non verrà generato per te.

Se lo utilizzi, stylesheet_link_tagverrà generato il collegamento corretto al tuo foglio di stile

Inoltre styles.cssdovrebbe essere in config.assets.precompilecui si trova l'elenco delle cose che sono precompilate


Vedo il file con le impronte digitali nella directory / public / assets /. Nel mio layout, ho questo: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>Non è corretto? `
emersonthis

Per qualche motivo, la distribuzione di produzione punta ancora ai file originali quando visualizzo l'origine, <link data-turbolinks-track="true" href="https://stackoverflow.com/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />ma i file javascript sono corretti! Non capisco perché le stesse configurazioni funzionano per i file .js ma non per .css.
emersonthis

Su Rails 5.0.0.beta3 ricevo questo avviso: DEPRECATION WARNING: serve_static_filesè deprecato e verrà rimosso in Rails 5.1. Si prega di utilizzare public_file_server.enabled = trueinvece.
GMA

@emersonthis Same! Js si carica perfettamente ma alcuni file CSS ottengono 404. Hai risolto questo problema?
IvRRimUm

È quasi SEMPRE un problema con la configurazione della pipeline degli asset. Se hai file in una posizione che non è predefinita, questo è quasi sicuramente il problema e devi comunicarlo alla pipeline di risorse utilizzando qualcosa come la prima risposta.
emerson questo

3

modificare la riga del file Production.rb

config.assets.compile = false

in

config.assets.compile = true

e aggiungi anche

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

perché compilare? non supponiamo di compilare la produzione mentre è in esecuzione
James Tan

1
NON FARE MAI QUESTO! Chiunque imposti config.assets.compile su true in produzione dovrebbe essere ucciso.
bkunzi01

2

Sto eseguendo Ubuntu Server 14.04 , Ruby 2.2.1 e Rails 4.2.4 Ho seguito un tutorial di distribuzione da DigitalOcean ed è andato tutto bene ma quando vado nel browser e inserisco l'indirizzo IP del mio VPS la mia app viene caricata ma senza stili e javascript.

L'app funziona con Unicorn e Nginx . Per risolvere questo problema, ho inserito il mio server utilizzando SSH con il mio utente "deployer" e sono andato al percorso della mia app che è "/ home / deployer / apps / blog" ed ho eseguito il seguente comando:

RAILS_ENV=production bin/rake assets:precompile

Quindi riavvio il VPS e il gioco è fatto! Per me funziona!

Spero possa essere utile per qualcun altro!


2

Se è impostata la precompilazione NON è necessario

config.assets.compile = true

poiché questo serve per servire le risorse dal vivo.

Il nostro problema era che avevamo solo la base chiave segreta di sviluppo impostata config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

È necessario accedere all'ambiente di produzione


1
come accennato in altre risposte di cui hai bisogno config.assets.precompile = ['*.js', '*.css', '*.css.erb'] e per correreRAILS_ENV=production bundle exec rake assets:precompile
xxjjnn

1
questo consente la compilazione di risorse durante la produzione in diretta, molto lenta, non corretta
James Tan

2

Cosa NON DEVI fare:

Alcuni dei miei colleghi sopra ti hanno consigliato di farlo:

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

La pipeline di asset rails dice dell'approccio di cui sopra:

Questa modalità utilizza più memoria, ha prestazioni inferiori rispetto a quella predefinita e non è consigliata. Vedi qui: ( http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation )

Cosa dovresti fare:

Precompila le tue risorse.

RAILS_ENV=production rake assets:precompile

Probabilmente puoi farlo con un compito rake.


Perché aggiungere artefatti build a git però? Puoi semplicemente aggiungere attività di rake al tuo processo di compilazione ed evitare enormi gitspam (specialmente se hai uglifier e gzipping, cosa che dovresti)
Dr.Strangelove

@ Dr.Strangelove Grazie per il tuo commento - non ne so abbastanza -: puoi elaborare / modificare il post originale?
BKSpurgeon

1

Il matcher predefinito per la compilazione dei file include application.js, application.css e tutti i file non JS / CSS (questo includerà automaticamente tutti gli asset immagine) dalle cartelle app / assets inclusi i tuoi gem:

Se hai altri manifesti o fogli di stile individuali e file JavaScript da includere, puoi aggiungerli all'array di precompilazione in config / initializers / assets.rb:

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

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


1

Prima di tutto controlla le tue risorse, potrebbe essere possibile che ci sia qualche errore nella precompilazione delle risorse.

Per precompilare gli asset in produzione ENV eseguire questo comando:

RAILS_ENV=production rake assets:precompile

Se mostra un errore, rimuovilo prima,

In caso di errore "variabile non definita", caricare quel file variabile prima di utilizzarlo in un altro file.

esempio:

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

nel file application.rb impostare la sequenza di precompilazione degli asset

esempio:

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']

1

Trovato questo:

L'opzione di configurazione config.serve_static_assetsè stata rinominata config.serve_static_filesper chiarirne il ruolo.

in 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?

Quindi imposta env RAILS_SERVE_STATIC_FILESo using Nginxper servire file statici. L'aggiunta config.serve_static_assets = truecontinuerà a funzionare, ma verrà rimossa in futuro.


1

non è consigliabile lasciare che capistrano esegua la precompilazione delle risorse, perché potrebbe richiedere anni e spesso timeout. provare a eseguire la precompilazione delle risorse locali.

Primo, impostare in config / application.rb config.assets.initialize_on_precompile = false quindi fare local RAILS_ENV=production bin/rake assets:precompile e aggiungere quelle public / assets a git.

e config / ambienti / development.rb, modifica il percorso delle risorse per evitare di utilizzare risorse precompilate:

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

Se hai problemi di connessione db, significa che hai un inizializzatore che usa db. un modo per aggirarlo è impostare un nuovo ambiente duplicando production.rb come forse production2 .rb, e in database.yml, aggiungere l' ambiente production2 con l' impostazione del database di sviluppo . Quindi fa

RAILS_ENV=production2 bin/rake assets:precompile

se stai ancora affrontando qualche problema con le risorse, ad esempio ckeditor, aggiungi il file js in config / initializers / assets.rb

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


0

Potrei sbagliarmi ma chi consiglia di cambiare

config.assets.compile = true

Il commento su questa riga è: # Non eseguire il fallback nella pipeline degli asset se manca un asset precompilato.

Ciò suggerisce che impostando questo su true non si risolve il problema, ma lo si aggira e si esegue la pipeline ogni volta. Questo deve sicuramente uccidere la tua performance e sconfiggere lo scopo del gasdotto?

Ho riscontrato lo stesso errore ed era dovuto all'applicazione in esecuzione in una sottocartella di cui rails non conosceva.

Quindi il mio file css era in home / sottocartella / app / public / .... ma rails stava cercando in home / app / public / ...

prova a spostare la tua app fuori dalla sottocartella oa dire a binari che si trova in una sottocartella.


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

Questo ha risolto il problema per me in produzione. Inseriscilo nella configurazione di nginx.


0

Anche noi abbiamo affrontato lo stesso problema dove siamo RAILS_ENV=production bundle exec rake assets:precompileriusciti ma le cose non hanno funzionato come previsto.
Abbiamo scoperto che l'unicorno era il principale colpevole qui.

Come nel tuo caso, anche noi eravamo soliti riavviare Unicorn dopo aver compilato le risorse. È stato notato che quando Unicorn viene riavviato, vengono riavviati solo i suoi processi di lavoro e non il processo principale.
Questo è il motivo principale per cui le risorse corrette non vengono servite.

Successivamente, dopo aver compilato le risorse, abbiamo interrotto e avviato unicorno in modo che anche il processo principale unicorno venga riavviato e vengano servite le risorse corrette.
Fermare e avviare l'unicorno comporta un tempo di inattività di circa 10 secondi rispetto al riavvio dell'unicorno. Questa è la soluzione alternativa che può essere utilizzata quando la soluzione a lungo termine è passare a puma da unicorno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.