Szyny 4: zasoby nie są ładowane w produkcji


116

Próbuję wprowadzić moją aplikację do produkcji, a ścieżki zasobów obrazu i css nie działają.

Oto, co obecnie robię:

  • Zasoby graficzne znajdują się w /app/assets/images/image.jpg
  • Arkusze stylów znajdują się w /app/assets/stylesheets/style.css
  • W moim układzie odwołuję się do pliku css w następujący sposób: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Przed ponownym uruchomieniem jednorożca uruchamiam RAILS_ENV=production bundle exec rake assets:precompilei się udaje i widzę pliki z odciskami palców w public/assetskatalogu.

Kiedy przeglądam moją witrynę, otrzymuję błąd 404 nie znaleziono dla adresu mysite.com/stylesheets/styles.css.

Co ja robię źle?

Aktualizacja: W moim układzie wygląda to tak:

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

Generowane źródło jest następujące:

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

Wygląda na to, że Railsy nie szukają poprawnie skompilowanych plików css. Ale to bardzo mylące, dlaczego działa poprawnie dla skryptów javascript (zwróć uwagę na /assets/****.jsścieżkę).


Czy możesz nam powiedzieć, jak ładujesz swój plik css? Wygląda na to, że z twojego błędu próbujesz połączyć go na stałe, zamiast używać stylesheet_link_tag.
kik

1
Właśnie dodane powyżej. Robię<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>
emersonthis

Ok, więc zaleciłbym dwie rzeczy: 1. sprawdź wygenerowane źródło, czy ta linia jest zapisana jako ścieżka do public/assetsi 2. sprawdź, czy nie ma gdzieś innej instrukcji próbującej załadować ten plik css (prawdopodobnie zakodowany na
stałe

Nie mogę powiedzieć, czy używanie .erb jest problemem, ponieważ nigdy tego nie robię: w .home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }rzeczywistości można go wymienić w zębatce na .home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }. Może spróbuj, jeśli to pomoże.
kik

Czy chcesz powiedzieć, że mogę wprowadzić to odniesienie do mojego pliku css jako dynamiczne bez dodawania rozszerzenia .erb? Zmieniłem to, ponieważ nie chciałem, aby łącze zrywało się, gdy jestem w trybie programowania.
emersonthis

Odpowiedzi:


105

W szynach 4 musisz wprowadzić poniższe zmiany:

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

To działa ze mną. użyj następującego polecenia, aby wstępnie skompilować zasoby

RAILS_ENV=production bundle exec rake assets:precompile

Powodzenia!


11
Myślałem, że ustawienie config.assets.compile na true zabije wydajność w środowisku produkcyjnym. także css.erb? kto tego używa? a co z sassem i kawą?
ahnbizcad

gdy żądane są pliki coffee i sass, są one przetwarzane przez procesory dostarczone przez klejnoty coffee-script i sass-rails, a następnie wysyłane z powrotem do przeglądarki jako odpowiednio JavaScript i CSS.
Rameshwar Vyevhare

1
Ten problem został już rozwiązany dla Rails 4, więc nie ma potrzeby używania turbo-sprocket-rails3 gem
Rameshwar Vyevhare

4
Przepraszam, nie jestem w stanie powiązać tego, co powiedziałeś, aby odpowiedzieć na moje pytanie.
ahnbizcad

1
Zwykle, gdy uruchamiasz serwer produkcyjny, będziesz uruchamiał Railsy z pasażerem, jednorożcem lub pumą za serwerem Apache lub nginx. Lepiej jest pozwolić Apache lub nginxowi obsługiwać pliki statyczne (js, css, obrazy), a serwer aplikacji Rails (puma, unicorn) obsługiwać kod i szablon Railsów. Aby to zrobić, należy wyłączyć config.serve_static_filesi skonfigurować alias w Apache i nginx assets.
Châu Hồng Lĩnh

85

Właśnie miałem ten sam problem i znalazłem to ustawienie w config / environment / production.rb:

# Rails 4:
config.serve_static_assets = false

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

Zmieniam to na true działało. Wygląda na to, że domyślnie Railsy oczekują, że skonfigurujesz swój serwer frontonu do obsługi żądań plików z folderu publicznego zamiast przekazywania ich do aplikacji Rails. Być może zrobiłeś to dla swoich plików javascript, ale nie dla arkuszy stylów CSS?

( Zobacz dokumentację Rails 5 ). Jak zauważono w komentarzach, w Railsach 5 możesz po prostu ustawić RAILS_SERVE_STATIC_FILESzmienną środowiskową, ponieważ domyślnym ustawieniem jest config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.


1
OSTRZEŻENIE O DEPRECATION: Zmieniono config.serve_static_assetsnazwę opcji konfiguracji na, config.serve_static_filesaby wyjaśnić jej rolę (umożliwia jedynie obsługę wszystkiego w publicfolderze i nie jest związana z potokiem zasobów). serve_static_assetsPs zostaną usunięte w szynach 5,0. Przeprowadź odpowiednią migrację plików konfiguracyjnych.
yekta

Wcześniej, kiedy stawiałem czoła temu problemowi, zmiana tej linii rozwiązała go za mnie, ale teraz mam do czynienia z tym ponownie (nie wiem, jak ciągle kończę w takich sytuacjach) i to nie wystarczy. Masz więcej sugestii, co może być nie tak?
IIIIIll

2
To powinna być akceptowana odpowiedź. Chociaż jest config.serve_static_filesw Rails 4.2 i config.public_file_server.enabledRails 5 . @see github.com/heroku/rails_serve_static_assets/blob/master/lib/…
Lucas Nelson

3
Rails 5.0.0.1 config / environment / production.rb zawiera, config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?więc możesz ustawić to inaczej dla swojego środowiska bez zmiany kodu, który jest wpisany do SCM.
tobinjim

Aby to włączyć: "eksportuj RAILS_SERVE_STATIC_FILES =" następnie uruchom "rails s -e production" Aby to wyłączyć: "unset RAILS_SERVE_STATIC_FILES"
Alfredo Osorio

32

W /config/environments/production.rbmusiałem to dodać:

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

.Js był już prekompilowany, ale i tak go dodałem. Najwyraźniej pliki .css i .css.erb nie pojawiają się automatycznie. W ^[^_]wyklucza partials z kompilowane - to wyrażenie regularne.

To trochę frustrujące, że dokumentacja jasno stwierdza, że ​​potok aktywów jest domyślnie włączony, ale nie wyjaśnia faktu, że dotyczy to tylko skryptów JavaScript.


Musisz dodać styles.css do config.assets.precompile
Frederick Cheung

23

Udało mi się rozwiązać ten problem poprzez zmianę: config.assets.compile = falsedo
config.assets.compile = trueIN/config/environments/production.rb

Aktualizacja (24 czerwca 2018 r.) : Ta metoda tworzy lukę w zabezpieczeniach, jeśli używana wersja Sprockets jest niższa niż 2.12.5, 3.7.2 lub 4.0.0.beta8


7
Czy to nie oznacza, że ​​Railsy kompilują zasoby zamiast, powiedzmy, ładować je z CDN?
Benjamin Oakes

@BenjaminOakes Tak, i tego właśnie chciałem
Yanofsky

2
Ten tryb zużywa więcej pamięci, działa gorzej niż domyślny i nie jest zalecany. Lepiej jest użyć proxy Nginx.
yekta

16

Dla Rails 5 powinieneś włączyć następujący kod konfiguracyjny:

config.public_file_server.enabled = true

Domyślnie Rails 5 są dostarczane z następującą linią konfiguracji:

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

Dlatego musisz ustawić zmienną środowiskową RAILS_SERVE_STATIC_FILESna true.


1
W przypadku Rails 5 powinienem dodać, ustawiam passenger_env_var RAILS_SERVE_STATIC_FILES true;w bloku lokalizacji mojej aplikacji w moim pliku nginx.conf.
Martin Velez,

10

Aby obsłużyć zasoby w produkcji, musisz wykonać 2 rzeczy:

  1. Wstępnie skompiluj zasoby.
  2. Przekaż zasoby z serwera do przeglądarki.

1) Aby wstępnie skompilować zasoby, masz kilka możliwości.

  • Możesz uruchomić rake assets:precompilena komputerze lokalnym, zatwierdzić go do kontroli kodu źródłowego (git), a następnie uruchomić program wdrożeniowy, na przykład capistrano. To nie jest dobry sposób przekazywania wstępnie skompilowanych zasobów do SCM.

  • Możesz napisać zadanie rake, które będzie uruchamiane RAILS_ENV=production rake assets:precompilena serwerach docelowych za każdym razem, gdy wdrażasz aplikację Rails w środowisku produkcyjnym, zanim zrestartujesz serwer.

Kod w zadaniu dla Capistrano będzie wyglądał podobnie do tego:

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) Teraz masz zasoby na serwerach produkcyjnych, musisz je udostępnić przeglądarce.

Ponownie masz kilka możliwości.

  • Włącz obsługę plików statycznych Railsów w config / environment / production.rb

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

    Używanie Railsów do obsługi plików statycznych może obniżyć wydajność Twojej aplikacji Railsowej.

  • Skonfiguruj nginx (lub Apache) do obsługi plików statycznych.

    Na przykład mój nginx, który został skonfigurowany do pracy z Pumą, wygląda następująco:

    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 nie generuje już wersji zasobu bez odcisku palca: arkusze stylów / style.css nie będą generowane dla Ciebie.

Jeśli użyjesz, stylesheet_link_tagzostanie wygenerowany poprawny link do twojego arkusza stylów

Dodatkowo styles.csspowinno być w config.assets.precompilektórym jest lista rzeczy, które są prekompilowane


Widzę plik z odciskami palców w katalogu / public / asset /. W moim układzie mam to: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>Czy to jest niepoprawne? '
emersonthis,

Z jakiegoś powodu wdrożenie produkcyjne nadal wskazuje oryginalne pliki, gdy przeglądam źródło. <link data-turbolinks-track="true" href="https://stackoverflow.com/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />Ale pliki javascript są poprawne! Nie rozumiem, dlaczego te same konfiguracje działają dla plików .js, ale nie .css.
emersonthis

Na Railsach 5.0.0.beta3 pojawia się ostrzeżenie: OSTRZEŻENIE O WYCOFANIU: serve_static_filesjest przestarzałe i zostanie usunięte w Railsach 5.1. Użyj public_file_server.enabled = truezamiast tego.
GMA

@emersonthis Same! Js ładuje się idealnie, ale niektóre pliki css otrzymują 404. Czy rozwiązałeś to?
IvRRimUm

To prawie ZAWSZE problem z konfiguracją potoku zasobów. Jeśli masz pliki w dowolnej lokalizacji, która nie jest domyślna, to prawie na pewno problem i musisz powiedzieć o tym potokowi zasobów, używając czegoś podobnego do pierwszej odpowiedzi.
emersonthis

3

zmień linię pliku Production.rb

config.assets.compile = false

w

config.assets.compile = true

a także dodaj

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

dlaczego kompilować? nie powinniśmy kompilować na produkcji podczas jej działania
James Tan

1
NIGDY TEGO NIE ROBIĆ! Każdy, kto ustawi config.assets.compile na true w środowisku produkcyjnym, powinien zostać nakręcony.
bkunzi01

2

Używam Ubuntu Server 14.04 , Ruby 2.2.1 i Rails 4.2.4. Śledziłem proces wdrażania z DigitalOcean i wszystko poszło dobrze, ale kiedy idę do przeglądarki i wprowadzam adres IP mojego VPS, moja aplikacja jest ładowana, ale bez style i javascript.

Aplikacja działa z Unicorn i Nginx . Aby rozwiązać ten problem, wszedłem na mój serwer za pomocą SSH z moim użytkownikiem „deployer” i przeszedłem do ścieżki mojej aplikacji, czyli „/ home / deployer / apps / blog”, i uruchomiłem następujące polecenie:

RAILS_ENV=production bin/rake assets:precompile

Następnie ponownie uruchamiam VPS i to wszystko! Mi to pasuje!

Mam nadzieję, że może to być przydatne dla kogoś innego!


2

Jeśli ustawiono prekompilację, NIE potrzebujesz

config.assets.compile = true

ponieważ ma to służyć aktywnym zasobom.

Nasz problem polegał na tym, że mieliśmy tylko ustawioną bazę tajnych kluczy programistycznych config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

Potrzebujesz wejścia do środowiska produkcyjnego


1
jak wspomniano w innych odpowiedziach, których potrzebujesz config.assets.precompile = ['*.js', '*.css', '*.css.erb'] i uruchomićRAILS_ENV=production bundle exec rake assets:precompile
xxjjnn

1
umożliwia to kompilację zasobów podczas produkcji na żywo, bardzo wolno, źle
James Tan

2

Czego NIE POWINIENEŚ robić:

Niektórzy z moich kolegów powyżej zalecili ci to zrobić:

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

Potok aktywów kolejowych mówi o powyższym podejściu:

Ten tryb zużywa więcej pamięci, działa gorzej niż domyślny i nie jest zalecany. Zobacz tutaj: ( http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation )

Co powinieneś zrobić:

Prekompiluj swoje zasoby.

RAILS_ENV=production rake assets:precompile

Prawdopodobnie możesz to zrobić za pomocą zadania prowizji.


Po co jednak dodawać artefakty kompilacji do gita? Możesz po prostu dodać zadanie rake do procesu kompilacji i uniknąć masowego gitspamu (szczególnie jeśli masz uglifier i gzipping, co powinieneś)
Dr Strangelove

@ Dr. Strangelove Dziękuję za komentarz - nie wiem wystarczająco dużo na ten temat -: czy możesz rozwinąć / edytować oryginalny post?
BKSpurgeon

1

Domyślny element dopasowujący do kompilowania plików obejmuje application.js, application.css i wszystkie pliki inne niż JS / CSS (automatycznie obejmie to wszystkie zasoby graficzne) z folderów aplikacji / zasobów, w tym klejnotów:

Jeśli masz inne manifesty lub indywidualne arkusze stylów i pliki JavaScript do dołączenia, możesz dodać je do tablicy prekompilacji w config / initializers / asset.rb:

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

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


1

Przede wszystkim sprawdź swoje zasoby, być może wystąpił błąd podczas wstępnej kompilacji zasobów.

Aby wstępnie skompilować zasoby w środowisku produkcyjnym, ENV uruchom to polecenie:

RAILS_ENV=production rake assets:precompile

Jeśli wyświetla błąd, najpierw go usuń,

W przypadku błędu „niezdefiniowana zmienna”, załaduj ten plik zmiennej przed użyciem go w innym pliku.

przykład:

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

w pliku application.rb ustaw sekwencję wstępnej kompilacji aktywów

przykład:

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

Znajdź to:

Nazwa opcji konfiguracji config.serve_static_assetszostała zmieniona na, config.serve_static_filesaby wyjaśnić jej rolę.

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

Ustaw więc env RAILS_SERVE_STATIC_FILESlub using Nginxdo obsługi plików statycznych. Dodawanie config.serve_static_assets = truebędzie nadal działać, ale zostanie usunięte w przyszłości.


1

nie jest zalecane, aby kapistrano dokonywał prekompilacji zasobów, ponieważ może to zająć całe wieki i często przerwać. spróbuj wykonać prekompilację zasobów lokalnych.

Najpierw ustaw w config / application.rb, config.assets.initialize_on_precompile = false a następnie wykonaj lokalne RAILS_ENV=production bin/rake assets:precompile i dodaj te public / asset do git.

i config / environment / development.rb, zmień ścieżkę do zasobów, aby uniknąć używania zasobów prekompilowanych:

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

Jeśli masz problem z połączeniem z bazą danych, oznacza to, że masz inicjator korzystający z bazy danych. sposobem obejścia tego problemu jest ustawienie nowego środowiska przez zduplikowanie pliku production.rb jako być może production2 .rb, a następnie w database.yml dodanie środowiska production2 z ustawieniem bazy danych deweloperskich . to zrób

RAILS_ENV=production2 bin/rake assets:precompile

jeśli nadal masz problem z zasobami, na przykład ckeditor, dodaj plik js do config / initializers / asset.rb

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


0

Może się mylę, ale ci, którzy zalecają zmianę

config.assets.compile = true

Komentarz w tym wierszu brzmi: # Nie wracaj do potoku aktywów, jeśli brakuje wstępnie skompilowanego zasobu.

Sugeruje to, że ustawiając to na true, nie naprawiasz problemu, ale raczej omijasz go i uruchamiasz potok za każdym razem. To z pewnością musi zabić twoją wydajność i zniweczyć cel rurociągu?

Miałem ten sam błąd i był to skutek działania aplikacji w podfolderze, o którym railsy nie wiedziały.

Więc mój plik css jest w home / subfolder / app / public / .... ale railsy szukały w home / app / public / ...

spróbuj przenieść swoją aplikację z podfolderu lub powiedzieć railsom, że jest w podfolderze.


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

To rozwiązało problem w produkcji. Umieść go w konfiguracji nginx.


0

Nawet my stanęliśmy przed tym samym problemem, w którym RAILS_ENV=production bundle exec rake assets:precompileudało się, ale rzeczy nie działały zgodnie z oczekiwaniami.
Okazało się, że głównym winowajcą był jednorożec.

Tak jak w Twoim przypadku, nawet my ponownie uruchamialiśmy jednorożca po skompilowaniu zasobów. Zauważono, że po ponownym uruchomieniu jednorożca uruchamiane są tylko jego procesy robocze, a nie proces główny.
Jest to główny powód, dla którego nie są wyświetlane prawidłowe zasoby.

Później, po skompilowaniu zasobów, zatrzymaliśmy się i uruchomiliśmy unicorn, aby proces wzorca unicorn również został ponownie uruchomiony, a prawidłowe zasoby były obsługiwane.
Zatrzymanie i uruchomienie jednorożca przynosi około 10 sekund przestoju w porównaniu do ponownego uruchomienia jednorożca. Jest to obejście, które można zastosować, gdy rozwiązanie długoterminowe jest przenoszone do pumy z jednorożca.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.