Rel 4: aset tidak dimuat dalam produksi

116

Saya mencoba memasukkan aplikasi saya ke dalam produksi dan image serta jalur aset css tidak berfungsi.

Inilah yang saya lakukan saat ini:

  • Aset gambar ada di /app/assets/images/image.jpg
  • Stylesheet ada di /app/assets/stylesheets/style.css
  • Dalam tata letak saya, saya mereferensikan file css seperti ini: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Sebelum memulai ulang unicorn, saya menjalankan RAILS_ENV=production bundle exec rake assets:precompiledan berhasil dan saya melihat file sidik jari di public/assetsdirektori.

Saat saya menelusuri situs saya, saya mendapatkan kesalahan 404 tidak ditemukan untuk mysite.com/stylesheets/styles.css.

Apa yang saya lakukan salah?

Pembaruan: Dalam tata letak saya, terlihat seperti ini:

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

Sumber yang dihasilkan adalah ini:

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

Sepertinya Rails tidak mencari file css yang telah dikompilasi dengan benar. Tetapi sangat membingungkan mengapa ini berfungsi dengan benar untuk javascripts (perhatikan /assets/****.jsjalurnya).

emersonthis
sumber
Bisakah Anda memberi tahu kami cara memuat file css Anda? Sepertinya dari kesalahan Anda bahwa Anda mencoba menautkannya ke hardlink daripada menggunakan stylesheet_link_tag.
kik
1
Baru saja ditambahkan di atas. Saya lakukan<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>
emersonthis
Oke, jadi saya akan merekomendasikan dua hal: 1. periksa sumber yang dihasilkan jika baris ini ditulis sebagai jalur ke public/assetsdan 2. periksa kembali apakah tidak ada instruksi lain di suatu tempat yang mencoba memuat file css itu (mungkin dengan kode keras)
kik
Saya tidak bisa mengatakan apakah menggunakan .erb adalah masalah karena saya tidak pernah melakukannya: .home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }sebenarnya dapat diganti dalam sproket dengan .home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }. Mungkin Anda bisa mencoba jika ini membantu.
kik
Apakah Anda mengatakan bahwa saya dapat membuat referensi itu di file css saya menjadi dinamis tanpa menambahkan ekstensi .erb? Saya mengubahnya karena saya tidak ingin tautan tersebut putus saat saya dalam mode pengembangan.
emersonthis

Jawaban:

105

Di rel 4 Anda perlu melakukan perubahan di bawah ini:

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

Ini bekerja dengan saya. gunakan perintah berikut untuk melakukan pra-kompilasi aset

RAILS_ENV=production bundle exec rake assets:precompile

Semoga berhasil!

Rameshwar Vyevhare
sumber
11
Saya pikir pengaturan config.assets.compile ke true akan mematikan kinerja dalam produksi. juga, css.erb? siapa yang menggunakan itu? dan bagaimana dengan sass dan kopi?
ahnbizcad
ketika file kopi dan sass diminta, mereka diproses oleh prosesor yang disediakan oleh permata script kopi dan sass-rails dan kemudian dikirim kembali ke browser sebagai JavaScript dan CSS masing-masing.
Rameshwar Vyevhare
1
Masalah ini sudah dipecahkan untuk Rails 4 sehingga tidak perlu menggunakan permata turbo-sprocket-rails3
Rameshwar Vyevhare
4
Maaf, saya tidak dapat menghubungkan apa yang Anda katakan untuk menjawab pertanyaan saya.
ahnbizcad
1
Biasanya, saat Anda menjalankan server produksi, Anda akan menjalankan Rails dengan penumpang atau unicorn atau puma di belakang server web Apache atau nginx. Lebih baik membiarkan Apache atau nginx menyajikan file statis (js, css, images), dan server aplikasi Rails (puma, unicorn) menyajikan kode dan template Rails. Untuk melakukannya, Anda harus mematikan config.serve_static_files, dan mengkonfigurasi alias di Apache dan nginx untuk ditangani assets.
Châu Hồng Lĩnh
85

Saya baru saja mengalami masalah yang sama dan menemukan pengaturan ini di config / environment / production.rb:

# Rails 4:
config.serve_static_assets = false

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

Menggantinya menjadi true berfungsi. Sepertinya secara default Rails mengharapkan Anda untuk mengonfigurasi server web front-end Anda untuk menangani permintaan file dari folder publik alih-alih mem-proxy-nya ke aplikasi Rails. Mungkin Anda telah melakukan ini untuk file javascript Anda tetapi bukan lembar gaya CSS Anda?

( Lihat dokumentasi Rails 5 ). Seperti disebutkan dalam komentar, dengan Rails 5 Anda dapat mengatur RAILS_SERVE_STATIC_FILESvariabel lingkungan, karena pengaturan default adalah config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.

davmac
sumber
1
PERINGATAN PERHATIAN: Opsi konfigurasi config.serve_static_assetstelah diubah namanya menjadi config.serve_static_filesuntuk memperjelas perannya (ini hanya memungkinkan penyajian semua yang ada di publicfolder dan tidak terkait dengan pipa aset). The serve_static_assetsalias akan dihapus dalam Rails 5.0. Harap migrasikan file konfigurasi Anda sebagaimana mestinya.
yekta
Sebelumnya ketika saya menghadapi masalah ini, mengubah baris itu telah menyelesaikannya untuk saya, tetapi sekarang saya menghadapinya lagi (saya tidak tahu bagaimana saya terus berakhir dalam situasi ini.) Dan ini tidak cukup. Ada lagi saran tentang apa yang mungkin salah?
IIllIIll
2
Ini harus menjadi jawaban yang diterima. Meskipun config.serve_static_filesdi Rails 4.2 dan config.public_file_server.enableddi 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 berisi config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?sehingga Anda dapat mengatur ini secara berbeda untuk lingkungan Anda tanpa mengubah kode yang diperiksa ke SCM Anda.
tobinjim
Untuk mengaktifkannya: "ekspor RAILS_SERVE_STATIC_FILES =" lalu jalankan "rails s -e production" Untuk menonaktifkannya: "unset RAILS_SERVE_STATIC_FILES"
Alfredo Osorio
32

Dalam /config/environments/production.rbaku harus menambahkan ini:

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

.Js sudah dikompilasi sebelumnya, tapi saya tetap menambahkannya. .Css dan .css.erb tampaknya tidak terjadi secara otomatis. The ^[^_]tidak termasuk parsial dari yang disusun - itu regexp.

Agak menjengkelkan bahwa dokumen dengan jelas menyatakan bahwa jalur pipa aset diaktifkan secara default tetapi tidak mengklarifikasi fakta bahwa hanya berlaku untuk javascript.

emersonthis
sumber
Anda perlu menambahkan styles.css ke config.assets.precompile
Frederick Cheung
23

Saya dapat mengatasi masalah ini dengan mengubah: config.assets.compile = falsemenjadi
config.assets.compile = truedalam/config/environments/production.rb

Pembaruan (24 Juni 2018) : Metode ini membuat kerentanan keamanan jika versi Sprocket yang Anda gunakan kurang dari 2.12.5, 3.7.2, atau 4.0.0.beta8

Yanofsky
sumber
7
Bukankah ini berarti bahwa Rails sedang mengompilasi aset, bukan, katakanlah, memuatnya dari CDN?
Benjamin Oakes
@BenjaminOakes Ya, dan itulah yang saya inginkan
Yanofsky
2
Mode ini menggunakan lebih banyak memori, bekerja lebih buruk daripada default dan tidak disarankan. Lebih baik menggunakan proxy nginx.
yekta
16

Untuk Rails 5, Anda harus mengaktifkan kode konfigurasi berikut:

config.public_file_server.enabled = true

Secara default, Rails 5 dikirimkan dengan baris konfigurasi ini:

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

Oleh karena itu, Anda perlu menyetel variabel lingkungan RAILS_SERVE_STATIC_FILESke true.

ytbryan
sumber
1
Untuk Rails 5, saya harus menambahkan, saya menetapkan passenger_env_var RAILS_SERVE_STATIC_FILES true;di blok lokasi aplikasi saya di file nginx.conf saya.
Martin Velez
10

Ada 2 hal yang harus Anda capai untuk melayani aset dalam produksi:

  1. Lakukan prakompilasi aset.
  2. Sajikan aset di server ke browser.

1) Untuk melakukan prakompilasi aset, Anda memiliki beberapa pilihan.

  • Anda dapat menjalankan rake assets:precompiledi komputer lokal Anda, memasukkannya ke kontrol kode sumber (git), lalu menjalankan program penerapan, misalnya capistrano. Ini bukan cara yang baik untuk memasukkan aset yang telah dikompilasi ke SCM.

  • Anda dapat menulis tugas rake yang berjalan RAILS_ENV=production rake assets:precompiledi server target setiap kali Anda menerapkan aplikasi Rails ke produksi, sebelum Anda memulai ulang server.

Kode dalam tugas untuk capistrano akan terlihat seperti ini:

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) Sekarang, Anda memiliki aset di server produksi, Anda perlu menyajikannya ke browser.

Sekali lagi, Anda punya beberapa pilihan.

  • Aktifkan penyajian file statis Rails di config / environment / production.rb

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

    Menggunakan Rails untuk menyajikan file statis akan mematikan kinerja aplikasi Rails Anda.

  • Konfigurasikan nginx (atau Apache) untuk menyajikan file statis.

    Misalnya, nginx saya yang dikonfigurasi untuk bekerja dengan Puma terlihat seperti ini:

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

Rails 4 tidak lagi menghasilkan versi non-sidik jari dari aset: stylesheets / style.css tidak akan dibuat untuk Anda.

Jika Anda menggunakan stylesheet_link_tagmaka tautan yang benar ke lembar gaya Anda akan dibuat

Selain itu styles.cssharus di config.assets.precompiledalam daftar hal-hal yang telah dikompilasi

Frederick Cheung
sumber
Saya melihat file sidik jari di / public / assets / direktori. Dalam tata letak saya, saya memiliki ini: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>Apakah ini salah? `
emersonthis
Untuk beberapa alasan, penerapan produksi masih mengarah ke file asli saat saya melihat sumbernya. <link data-turbolinks-track="true" href="https://stackoverflow.com/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />Tetapi file javascriptnya benar! Saya tidak mengerti mengapa konfigurasi yang sama berfungsi untuk file .js tetapi tidak .css.
emersonthis
Di Rails 5.0.0.beta3, saya mendapatkan peringatan ini: PERINGATAN DEPRECATION: serve_static_filestidak digunakan lagi dan akan dihapus di Rails 5.1. Silakan gunakan public_file_server.enabled = truesebagai gantinya.
GMA
@emersonthis Sama! Js memuat dengan sempurna tetapi beberapa file css mendapatkan 404. Apakah Anda menyelesaikan ini?
IvRRimUm
Ini hampir SELALU menjadi masalah dengan konfigurasi jalur aset. Jika Anda memiliki file di lokasi mana pun yang bukan default, itu hampir pasti masalahnya dan Anda perlu memberi tahu pipeline aset tentang hal itu menggunakan sesuatu seperti jawaban pertama.
emersonthis
3

ubah baris file Production.rb Anda

config.assets.compile = false

ke

config.assets.compile = true

dan juga menambahkan

config.assets.precompile =  ['*.js', '*.css', '*.css.erb']
Jassa Mahal
sumber
mengapa mengkompilasi? kami tidak akan mengkompilasi produksi saat sedang berjalan
James Tan
1
JANGAN PERNAH LAKUKAN INI! Siapa pun yang menyetel config.assets.compile ke true dalam produksi harus diambil gambarnya.
bkunzi01
2

Saya menjalankan Ubuntu Server 14.04 , Ruby 2.2.1 dan Rails 4.2.4. Saya telah mengikuti turorial penyebaran dari DigitalOcean dan semuanya berjalan dengan baik tetapi ketika saya pergi ke browser dan memasukkan alamat IP dari VPS saya, aplikasi saya dimuat tetapi tanpa gaya dan javascript.

Aplikasi ini berjalan dengan Unicorn dan Nginx . Untuk memperbaiki masalah ini, saya memasuki server saya menggunakan SSH dengan 'deployer' pengguna saya dan pergi ke jalur aplikasi saya yaitu '/ home / deployer / apps / blog' dan jalankan perintah berikut:

RAILS_ENV=production bin/rake assets:precompile

Kemudian saya baru saja me-restart VPS dan hanya itu! Ini berhasil untuk saya!

Semoga bisa bermanfaat untuk orang lain!

alexventuraio
sumber
2

Jika precompile disetel, Anda TIDAK perlu

config.assets.compile = true

karena ini untuk melayani aset secara langsung.

Masalah kami adalah kami hanya memiliki basis kunci rahasia pengembangan config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

Perlu masuk untuk lingkungan produksi

xxjjnn
sumber
1
seperti yang disebutkan dalam jawaban lain yang Anda perlukan config.assets.precompile = ['*.js', '*.css', '*.css.erb'] dan jalankanRAILS_ENV=production bundle exec rake assets:precompile
xxjjnn
1
ini memungkinkan kompilasi aset saat hidup dalam produksi, sangat lambat, tidak benar
James Tan
2

Apa yang HARUS Anda lakukan:

Beberapa rekan saya di atas telah merekomendasikan Anda untuk melakukan ini:

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

Pipa aset rel mengatakan tentang pendekatan di atas:

Mode ini menggunakan lebih banyak memori, bekerja lebih buruk daripada default dan tidak disarankan. Lihat di sini: ( http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation )

Apa yang HARUS Anda lakukan:

Pra-kompilasi aset Anda.

RAILS_ENV=production rake assets:precompile

Anda mungkin dapat melakukannya dengan tugas menyapu.

BKSpurgeon
sumber
Mengapa menambahkan artefak build ke git? Anda cukup menambahkan tugas rake ke proses pembuatan Anda dan menghindari gitspam besar-besaran (terutama jika Anda memiliki uglifier dan gzipping, yang seharusnya)
Dr. Strangelove
@ Dr.Strangelove Terima kasih atas komentar Anda - Saya tidak cukup tahu tentang itu -: dapatkah Anda menjelaskan / mengedit postingan aslinya?
BKSpurgeon
1

Pencocokan default untuk mengompilasi file termasuk application.js, application.css dan semua file non-JS / CSS (ini akan mencakup semua aset gambar secara otomatis) dari folder app / assets termasuk permata Anda:

Jika Anda memiliki manifes lain atau stylesheet individual dan file JavaScript untuk disertakan, Anda dapat menambahkannya ke array precompile di 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
sumber
1

Pertama-tama periksa aset Anda, mungkin saja ada kesalahan dalam pra-kompilasi aset.

Untuk melakukan pra-kompilasi aset dalam produksi ENV, jalankan perintah ini:

RAILS_ENV=production rake assets:precompile

Jika itu menunjukkan kesalahan, hapus itu dulu,

Jika terjadi kesalahan "variabel tidak ditentukan", muat file variabel tersebut sebelum menggunakannya di file lain.

contoh:

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

dalam file application.rb mengatur urutan pra-kompilasi aset

contoh:

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

Menemukan ini:

Opsi konfigurasi config.serve_static_assetstelah diubah namanya menjadi config.serve_static_filesuntuk memperjelas perannya.

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

Jadi setel env RAILS_SERVE_STATIC_FILESatau use Nginxuntuk melayani file statis. Tambahkan config.serve_static_assets = trueakan tetap berfungsi, tetapi dihapus di masa mendatang.

Daniel Wei
sumber
1

tidak disarankan untuk membiarkan capistrano melakukan prakompilasi aset, karena dapat memakan waktu lama dan seringkali waktu habis. coba lakukan precompile aset lokal.

Pertama, setel di config / application.rb config.assets.initialize_on_precompile = false lalu lakukan local RAILS_ENV=production bin/rake assets:precompile dan tambahkan public / assets itu ke git.

dan config / environment / development.rb, ubah jalur aset Anda untuk menghindari penggunaan aset yang telah dikompilasi sebelumnya:

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

Jika Anda memiliki masalah koneksi db, berarti Anda memiliki penginisialisasi yang menggunakan db. salah satu cara untuk mengatasinya adalah dengan menyetel lingkungan baru dengan menduplikasi production.rb sebagai mungkin production2 .rb, dan di database.yml, menambahkan lingkungan produksi2 dengan pengaturan db pengembangan . lalu lakukan

RAILS_ENV=production2 bin/rake assets:precompile

jika Anda masih menghadapi masalah dengan aset, misalnya ckeditor, tambahkan file js ke config / initializers / assets.rb

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

James Tan
sumber
0

Saya mungkin salah tetapi mereka yang merekomendasikan perubahan

config.assets.compile = true

Komentar di baris ini berbunyi: #Jangan mundur ke jalur aset jika aset yang telah dikompilasi terlewat.

Ini menunjukkan bahwa dengan menyetel ini ke true, Anda tidak memperbaiki masalah, melainkan melewatinya dan menjalankan pipeline setiap saat. Ini pasti harus mematikan kinerja Anda dan mengalahkan tujuan pipa?

Saya mengalami kesalahan yang sama dan itu karena aplikasi yang berjalan di sub folder yang tidak diketahui oleh rel.

Jadi file css saya ada di home / subfolder / app / public / .... tapi rails mencari di home / app / public / ...

coba pindahkan aplikasi Anda keluar dari subfolder atau beri tahu rel bahwa itu ada di subfolder.

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

Ini memperbaiki masalah saya dalam produksi. Masukkan ke konfigurasi nginx.

Pedro Adame Vergara
sumber
0

Meskipun kami menghadapi masalah yang sama dimana RAILS_ENV=production bundle exec rake assets:precompileberhasil tetapi hal-hal tidak berjalan sesuai harapan.
Kami menemukan bahwa unicorn adalah penyebab utama di sini.

Sama seperti kasus Anda, bahkan kami biasa memulai ulang unicorn setelah mengompilasi aset. Telah diketahui bahwa ketika unicorn di-restart, hanya proses pekerja yang di-restart dan bukan proses master.
Inilah alasan utama mengapa aset yang benar tidak terlayani.

Kemudian, setelah mengompilasi aset, kami menghentikan dan memulai unicorn sehingga proses master unicorn juga dimulai ulang dan aset yang benar sedang disajikan.
Menghentikan dan memulai unicorn membawa sekitar 10 detik waktu henti jika dibandingkan dengan memulai ulang unicorn. Ini adalah solusi yang bisa digunakan dimana solusi jangka panjang dipindahkan ke puma dari unicorn.

Bhavya Keniya
sumber