Trilhos 4: ativos não carregados na produção


116

Estou tentando colocar meu aplicativo em produção e os caminhos de recursos de imagem e css não estão funcionando.

Aqui está o que estou fazendo atualmente:

  • Ativos de imagem em /app/assets/images/image.jpg
  • As folhas de estilo estão em /app/assets/stylesheets/style.css
  • Em meu layout, faço referência ao arquivo css desta forma: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Antes de reiniciar o unicórnio, eu corro RAILS_ENV=production bundle exec rake assets:precompilee ele consegue e vejo os arquivos de impressão digital no public/assetsdiretório.

Quando eu navego em meu site, recebo um erro 404 não encontrado para mysite.com/stylesheets/styles.css.

O que estou fazendo de errado?

Atualização: no meu layout, é assim:

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

A fonte de geração é esta:

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

Parece que o Rails não está procurando apropriadamente pelos arquivos css compilados. Mas é muito confuso porque está funcionando corretamente para javascripts (observe o /assets/****.jscaminho).


Você pode nos dizer como carrega seu arquivo css? Pelo seu erro, parece que você tenta fazer um hardlink em vez de usar stylesheet_link_tag.
— kik

1
Apenas adicionado acima. Estou fazendo<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>
— finalização em

Ok, então eu recomendaria duas coisas: 1. verifique na fonte gerada se esta linha está escrita como caminho para public/assetse 2. verifique se não há outra instrução em algum lugar tentando carregar aquele arquivo css (presumivelmente codificado)
— kik

Não posso dizer se usar .erb é um problema porque eu nunca faço isso: .home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }pode realmente ser substituído na roda dentada por .home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }. Talvez você possa tentar se isso ajudar.
— kik

Você está dizendo que posso tornar essa referência dinâmica em meu arquivo css sem adicionar a extensão .erb? Eu mudei porque não queria que o link quebrasse quando estou no modo de desenvolvimento.
— início em

Respostas:


105

No trilho 4, você precisa fazer as alterações abaixo:

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

Isso funciona comigo. use o seguinte comando para pré-compilar recursos

RAILS_ENV=production bundle exec rake assets:precompile

Boa sorte!


11
Achei que definir config.assets.compile como true prejudicaria o desempenho na produção. também, css.erb? quem usa isso? e que tal ousadia e café?
— ahnbizcad

quando os arquivos coffee e sass são solicitados, eles são processados ​​pelos processadores fornecidos pelas gemas coffee-script e sass-rails e, em seguida, enviados de volta ao navegador como JavaScript e CSS, respectivamente.
— Rameshwar Vyevhare 01 de

1
Este problema já foi resolvido para Rails 4 e, portanto, não há necessidade de usar turbo-sprocket-rails3 gem
— Rameshwar Vyevhare 01/09/2014

4
Desculpe, não estou conseguindo fazer a conexão do que você disse para responder à minha pergunta.
— ahnbizcad 01 de

1
Normalmente, quando você executa o servidor de produção, você executa o Rails com passageiro ou unicórnio ou puma por trás do servidor Apache ou nginx. É melhor deixar Apache ou nginx servir arquivos estáticos (js, css, imagens), e o servidor de aplicação Rails (puma, unicórnio) servir código Rails e template. Para fazer isso, você deve desligar config.serve_static_filese configurar o alias no Apache e nginx para lidar com ele assets.
— Châu Hồng Lĩnh

85

Acabei de ter o mesmo problema e encontrei esta configuração em config / environment / production.rb:

# Rails 4:
config.serve_static_assets = false

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

Mudar para fazê- truelo funcionar. Parece que por padrão o Rails espera que você tenha configurado seu servidor web front-end para lidar com solicitações de arquivos fora da pasta pública ao invés de procurá-los para o aplicativo Rails. Talvez você tenha feito isso para seus arquivos javascript, mas não para suas folhas de estilo CSS?

( Veja a documentação do Rails 5 ). Como notado nos comentários, com Rails 5 você pode apenas definir a RAILS_SERVE_STATIC_FILESvariável de ambiente, já que a configuração padrão é config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.


1
AVISO DE DEPRECAÇÃO: A opção de configuração config.serve_static_assetsfoi renomeada para config.serve_static_filesesclarecer sua função (ela apenas permite servir tudo na publicpasta e não está relacionada ao pipeline de ativos). O serve_static_assetsalias será removido no Rails 5.0. Migre seus arquivos de configuração de acordo.
— yekta 01 de

Antes, quando eu estava enfrentando esse problema, mudar essa linha tinha resolvido para mim, mas agora estou enfrentando de novo (não sei como continuo terminando nessas situações) e isso não é suficiente. Mais alguma sugestão sobre o que pode estar errado?
— IIllIIll

2
Esta deve ser a resposta aceita. Embora esteja config.serve_static_filesno Rails 4.2 e config.public_file_server.enabledno 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 contém config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?para que você possa definir isso de forma diferente para o seu ambiente, sem alterar o código que é verificado em seu SCM.
— tobinjim de

Para habilitá-lo: "export RAILS_SERVE_STATIC_FILES =" então você executa "rails s -e production" Para desabilitá-lo: "unset RAILS_SERVE_STATIC_FILES"
— Alfredo Osorio

32

Em /config/environments/production.rbeu tive que adicionar isto:

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

O .js já estava sendo pré-compilado, mas eu o adicionei mesmo assim. Aparentemente, .css e .css.erb não acontecem automaticamente. O ^[^_]exclui parciais de serem compilados - é um regexp.

É um pouco frustrante que os documentos afirmem claramente que o pipeline de ativos ESTÁ habilitado por padrão, mas não esclarece o fato de que se aplica apenas a javascripts.


Você precisa adicionar styles.css a config.assets.precompile
— Frederick Cheung

23

Consegui resolver este problema mudando: config.assets.compile = falsepara
config.assets.compile = trueem/config/environments/production.rb

Atualização (24 de junho de 2018) : este método cria uma vulnerabilidade de segurança se a versão do Sprockets que você está usando for inferior a 2.12.5, 3.7.2 ou 4.0.0.beta8


7
Isso não significa que o Rails está compilando os ativos em vez de, digamos, carregá-los de um CDN?
— Benjamin Oakes

@BenjaminOakes Sim, e era isso que eu queria
— Yanofsky

2
Este modo usa mais memória, tem um desempenho inferior ao padrão e não é recomendado. Melhor usar um proxy nginx.
— yekta 01 de

16

Para Rails 5, você deve habilitar o seguinte código de configuração:

config.public_file_server.enabled = true

Por padrão, o Rails 5 vem com esta linha de configuração:

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

Portanto, você precisará definir a variável de ambiente RAILS_SERVE_STATIC_FILEScomo true.


1
Para Rails 5, devo acrescentar, eu defini passenger_env_var RAILS_SERVE_STATIC_FILES true;no bloco de localização do meu aplicativo em meu arquivo nginx.conf.
— Martin Velez

10

Existem 2 coisas que você deve realizar para atender aos ativos em produção:

  1. Pré-compilar os ativos.
  2. Sirva os ativos do servidor para o navegador.

1) Para pré-compilar os ativos, você tem várias opções.

  • Você pode executar rake assets:precompileem sua máquina local, confirmá-lo no controle de código-fonte (git) e, em seguida, executar o programa de implantação, por exemplo, capistrano. Essa não é uma boa maneira de comprometer ativos pré-compilados ao SCM.

  • Você pode escrever uma tarefa rake que é executada RAILS_ENV=production rake assets:precompilenos servidores de destino cada vez que você implanta seu aplicativo Rails para produção, antes de reiniciar o servidor.

O código em uma tarefa para capistrano será semelhante a este:

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) Agora, você tem os ativos nos servidores de produção e precisa veiculá-los no navegador.

Novamente, você tem várias opções.

  • Ative o arquivo estático do Rails servindo em config / environment / production.rb

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

    Usar Rails para servir arquivos estáticos vai matar o desempenho de seu aplicativo Rails.

  • Configure o nginx (ou Apache) para servir arquivos estáticos.

    Por exemplo, meu nginx que foi configurado para funcionar com Puma se parece com isto:

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

4

O Rails 4 não gera mais a versão sem impressão digital do ativo: stylesheets / style.css não serão gerados para você.

Se você usar stylesheet_link_tag, o link correto para sua folha de estilo será gerado

Além disso, styles.cssdeve estar em config.assets.precompilequal está a lista de coisas que são pré-compiladas


Vejo o arquivo com impressão digital no diretório / public / assets /. Em meu layout, tenho o seguinte: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>Isso está incorreto? `
— emerso em

Por algum motivo, a implantação de produção ainda está apontando para os arquivos originais quando eu visualizo o código-fonte. <link data-turbolinks-track="true" href="https://stackoverflow.com/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />Mas os arquivos javascript estão corretos! Não entendo por que as mesmas configurações funcionam para arquivos .js, mas não para .css.
— início em

No Rails 5.0.0.beta3 eu recebo este aviso: AVISO DE DEPRECAÇÃO: serve_static_filesestá obsoleto e será removido no Rails 5.1. Em public_file_server.enabled = truevez disso, use .
— GMA

@emersonthis Same! Js carrega perfeitamente, mas alguns arquivos css ficam 404. Você resolveu isso?
— IvRRimUm

É quase SEMPRE um problema com a configuração do pipeline de ativos. Se você tiver arquivos em qualquer local que não seja o padrão, esse é quase definitivamente o problema e você precisa informar o pipeline de ativos sobre isso usando algo como a primeira resposta.
— emersonthis

3

mude sua linha de arquivo Production.rb

config.assets.compile = false

para dentro

config.assets.compile = true

e também adicionar

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

por que compilar? não devemos compilar em produção durante sua execução
— James Tan

1
NUNCA FAÇA ISSO! Qualquer pessoa que definir config.assets.compile como true na produção deve ser morta.
— bkunzi01

2

Estou executando o Ubuntu Server 14.04 , Ruby 2.2.1 e Rails 4.2.4 Eu segui um turorial de implantação da DigitalOcean e tudo correu bem, mas quando vou ao navegador e o endereço IP do meu VPS meu aplicativo é carregado, mas sem estilos e javascript.

O aplicativo está sendo executado com Unicorn e Nginx . Para corrigir esse problema, entrei em meu servidor usando SSH com meu usuário 'deployer' e acessei o caminho do meu aplicativo que é '/ home / deployer / apps / blog' e execute o seguinte comando:

RAILS_ENV=production bin/rake assets:precompile

Depois é só reiniciar o VPS e pronto! Funciona para mim!

Espero que possa ser útil para outra pessoa!


2

Se a pré-compilação estiver definida, você NÃO precisa

config.assets.compile = true

pois isso é para servir ativos ao vivo.

Nosso problema era que só tínhamos a base da chave secreta de desenvolvimento definida em config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

Precisa de entrada para ambiente de produção


1
conforme mencionado em outras respostas que você precisa config.assets.precompile = ['*.js', '*.css', '*.css.erb'] e para executarRAILS_ENV=production bundle exec rake assets:precompile
— xxjjnn

1
isso permite a compilação de recursos durante a produção ao vivo, muito lento, incorreto
— James Tan

2

O que você NÃO DEVE fazer:

Alguns dos meus colegas acima recomendaram que você fizesse isso:

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

O pipeline de ativos do Rails diz sobre a abordagem acima:

Este modo usa mais memória, tem um desempenho inferior ao padrão e não é recomendado. Veja aqui: ( http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation )

O que você deveria fazer:

Pré-compile seus ativos.

RAILS_ENV=production rake assets:precompile

Você provavelmente pode fazer isso com uma tarefa de rake.


Por que adicionar artefatos de construção ao git? Você pode simplesmente adicionar a tarefa rake ao seu processo de construção e evitar gitspam massivo (especialmente se você tiver uglifier e gzipping ativado, o que você deve)
— Dr.Strangelove

@ Dr.Strangelove Obrigado pelo seu comentário - não sei o suficiente sobre isso -: você pode elaborar / editar a postagem original?
— BKSpurgeon

1

O matcher padrão para compilar arquivos inclui application.js, application.css e todos os arquivos não JS / CSS (isso incluirá todos os ativos de imagem automaticamente) das pastas app / assets incluindo suas joias:

Se você tiver outros manifestos ou folhas de estilo individuais e arquivos JavaScript para incluir, poderá adicioná-los à matriz de pré-compilação em 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

Em primeiro lugar, verifique seus ativos, pode ser possível que haja algum erro na pré-compilação de ativos.

Para pré-compilar ativos em produção ENV execute este comando:

RAILS_ENV=production rake assets:precompile

Se mostrar erro, remova-o primeiro,

Em caso de erro de "variável indefinida", carregue esse arquivo de variável antes de usá-lo em outro arquivo.

exemplo:

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

no arquivo application.rb conjunto de sequência de pré-compilação de ativos

exemplo:

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

Encontrei isto:

A opção de configuração config.serve_static_assetsfoi renomeada config.serve_static_filespara esclarecer sua função.

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

Portanto, defina env RAILS_SERVE_STATIC_FILESou using Nginxpara servir arquivos estáticos. Adicionar config.serve_static_assets = trueainda funcionará, mas será removido no futuro.


1

não é recomendado deixar o capistrano fazer a pré-compilação dos ativos, porque pode levar anos e muitas vezes expirar. tente fazer a pré-compilação dos ativos locais.

Primeiro, defina em config / application.rb config.assets.initialize_on_precompile = false e faça local RAILS_ENV=production bin/rake assets:precompile e adicione esses public / assets ao git.

e config / environment / development.rb, altere o caminho do seu ativo para evitar o uso de ativos pré-compilados:

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

Se você tiver problema de conexão db, significa que você tem um inicializador que usa db. uma maneira de contornar isso é definir um novo ambiente duplicando production.rb como, talvez, production2 .rb, e em database.yml, adicionar o ambiente production2 com configuração de banco de dados de desenvolvimento . então faça

RAILS_ENV=production2 bin/rake assets:precompile

se você ainda está enfrentando algum problema com ativos, por exemplo ckeditor, adicione o arquivo js em config / initializers / assets.rb

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


0

Posso estar errado, mas aqueles que recomendam mudar

config.assets.compile = true

O comentário nesta linha diz: # Não faça fallback para o pipeline de recursos se um recurso pré-compilado for perdido.

Isso sugere que, ao definir isso como true, você não está corrigindo o problema, mas sim ignorando-o e executando o pipeline todas as vezes. Isso certamente deve matar seu desempenho e anular o propósito do pipeline?

Eu tive esse mesmo erro e foi devido ao aplicativo rodando em uma subpasta que o rails não conhecia.

Portanto, meu arquivo css estava em home / subfolder / app / public / .... mas rails estava em home / app / public / ...

tente mover seu aplicativo para fora da subpasta ou dizer ao Rails que ele está em uma subpasta.


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

Isso resolveu o meu problema na produção. Coloque-o na configuração do nginx.


0

Mesmo nós enfrentamos o mesmo problema onde RAILS_ENV=production bundle exec rake assets:precompiletivemos sucesso, mas as coisas não funcionaram como esperado.
Descobrimos que o unicórnio era o principal culpado aqui.

Como no seu caso, mesmo nós costumávamos reiniciar o Unicórnio após compilar os ativos. Percebeu-se que quando o unicórnio é reiniciado, apenas seus processos de trabalho são reiniciados e não o processo mestre.
Este é o principal motivo pelo qual os ativos corretos não são veiculados.

Mais tarde, após compilar os ativos, paramos e iniciamos o unicórnio para que o processo mestre do unicórnio também seja reiniciado e os ativos corretos sejam entregues.
Parar e iniciar o unicórnio traz cerca de 10 segundos de tempo de inatividade em comparação com reiniciá-lo. Esta é a solução alternativa que pode ser usada quando a solução de longo prazo é mudar de unicórnio para puma.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.