config.assets.compile = true dalam produksi Rails, mengapa tidak?

185

Aplikasi Rails default yang diinstal oleh rails newtelah config.assets.compile = falsedalam produksi.

Dan cara biasa untuk melakukan sesuatu adalah dengan menjalankan rake assets:precompilesebelum menggunakan aplikasi Anda, untuk memastikan semua aset pipa aset dikompilasi.

Jadi apa yang terjadi jika saya mengatur config.assets.compile = trueproduksi?

Saya tidak perlu lari precompilelagi. Apa yang saya percaya akan terjadi adalah pertama kali suatu aset diminta, itu akan dikompilasi. Ini akan menjadi hit kinerja yang pertama kali (dan itu berarti Anda umumnya memerlukan js runtime dalam produksi untuk melakukannya). Tapi selain kerugian ini, setelah aset itu disusun dengan malas, saya pikir semua akses selanjutnya ke aset itu tidak akan ada memukul kinerja, kinerja aplikasi akan persis sama seperti dengan aset dikompilasi setelah kompilasi ini awal pertama-hit malas. Apakah ini benar?

Apakah ada sesuatu yang saya lewatkan? Adakah alasan lain untuk tidak menetapkan config.assets.compile = trueproduksi? Jika saya memiliki runtime JS dalam produksi, dan saya bersedia mengambil tradeoff kinerja terdegradasi untuk akses pertama suatu aset, sebagai imbalan karena tidak harus menjalankanprecompile , apakah ini masuk akal?

Jrochkind
sumber
1
Peringatan, versi lama sprocket berisi bug dan jika config.assets.compile dikonfigurasikan dengan benar, ada risiko kerentanan trasversal direktori ( blog.heroku.com/rails-asset-pipeline-vulnerability )
Mauro
Beginilah seharusnya Stackoverflow berfungsi. Pertanyaan yang ditulis dengan baik dan jawaban yang ditulis dengan baik. Aku cinta kalian berdua op dan @ richard-hulse.
schmijos

Jawaban:

259

Saya menulis sedikit panduan itu.

Anda pasti tidak ingin tinggal kompilasi dalam produksi.

Ketika Anda telah mengkompilasi, inilah yang terjadi:

Setiap permintaan untuk file di / aset diteruskan ke Sprockets. Yang pertama permintaan untuk masing-masing dan setiap aset itu dikompilasi dan di-cache dalam apa pun Rails gunakan untuk cache (biasanya sistem file).

Pada permintaan berikutnya Sprockets menerima permintaan tersebut dan harus mencari nama file sidik jari, periksa apakah file (gambar) atau file (css dan js) yang membentuk aset tidak diubah, dan kemudian jika ada versi cache melayani itu.

Itu adalah segalanya di folder aset dan di folder vendor / aset apa pun yang digunakan oleh plugin.

Itu banyak overhead seperti, jujur, kode tidak dioptimalkan untuk kecepatan.

Ini akan berdampak pada seberapa cepat aset beralih ke klien, dan akan berdampak negatif terhadap waktu pemuatan halaman situs Anda.

Bandingkan dengan yang standar:

Ketika aset dikompilasi dan dikompilasi dimatikan, aset dikompilasi dan sidik jari ke public/assets . Sprockets mengembalikan tabel pemetaan dari dataran ke nama file sidik jari ke Rails, dan Rails menulis ini ke sistem file. File manifes (YML di Rails 3 atau JSON dengan nama acak di Rails 4) dimuat ke dalam Memory by Rails saat startup dan di-cache untuk digunakan oleh metode pembantu aset.

Ini membuat pembuatan halaman dengan aset sidik jari yang benar menjadi sangat cepat, dan penyajian file itu sendiri adalah web-server-dari-filesystem yang cepat. Keduanya secara dramatis lebih cepat daripada kompilasi langsung.

Untuk mendapatkan keuntungan maksimal dari pipeline dan sidik jari, Anda perlu mengatur header masa depan jauh di server web Anda, dan mengaktifkan kompresi gzip untuk file js dan css. Sprockets menulis versi aset yang di-gzip yang dapat Anda atur untuk digunakan server Anda, menghilangkan keharusan untuk melakukannya untuk setiap permintaan.

Ini memberikan aset kepada klien secepat mungkin, dan dalam ukuran sekecil mungkin, mempercepat tampilan sisi-klien dari halaman, dan mengurangi permintaan (dengan header yang jauh di masa depan).

Jadi jika Anda tinggal mengompilasinya adalah:

  1. Sangat lambat
  2. Tidak memiliki kompresi
  3. Akan memengaruhi waktu render halaman

Melawan

  1. Secepat mungkin
  2. Terkompresi
  3. Hapus kompresi yang tidak sengaja terdengar dari server (opsional).
  4. Minimalkan waktu render halaman.

Edit: (Jawaban untuk menindaklanjuti komentar)

Pipa dapat diubah untuk dikompilasi pada permintaan pertama tetapi ada beberapa penghalang utama untuk melakukannya. Yang pertama adalah harus ada tabel pencarian untuk nama sidik jari atau metode pembantu terlalu lambat. Di bawah senario kompilasi berdasarkan permintaan akan perlu ada cara untuk menambahkan ke tabel pencarian karena setiap aset baru dikompilasi atau diminta.

Juga, seseorang harus membayar harga pengiriman aset lambat untuk periode waktu yang tidak diketahui sampai semua aset dikompilasi dan di tempat.

Defaultnya, di mana harga kompilasi semuanya dibayar secara off-line pada satu waktu, tidak memengaruhi pengunjung publik dan memastikan bahwa semuanya berfungsi sebelum semuanya ditayangkan.

Pemecah masalah adalah bahwa hal itu menambah banyak kerumitan pada sistem produksi.

[Sunting, Juni 2015] Jika Anda membaca ini karena Anda mencari solusi untuk waktu kompilasi yang lambat selama penerapan, maka Anda dapat mempertimbangkan untuk mengkompilasi ulang aset secara lokal. Informasi tentang ini ada di panduan jalur pipa aset . Ini memungkinkan Anda mengkompilasi secara lokal hanya ketika ada perubahan, komit itu, dan kemudian memiliki penyebaran cepat tanpa tahap precompile.

Richard Hulse
sumber
1
Terima kasih, saya menerima jawaban Anda. Tetapi sekarang pertanyaan saya adalah, oke, ia tidak melakukannya sekarang, tetapi menurut Anda apakah Asset Pipeline dapat memiliki fitur di mana ia mengkompilasi dengan malas pada permintaan pertama, melakukannya persis seperti precompile, termasuk menulis ke ./public dan memperbarui manifes sidik jari?
jrochkind
Lihat di atas. Apakah ini masalah karena Capistrano tidak bekerja untuk Anda?
Richard Hulse
Saya tidak menggunakan Capistrano. Saya tidak perlu sebelumnya, kompleksitas tambahan tidak sepadan. Mungkin pipa aset adalah sedotan yang mematahkan unta kembali dan membutuhkannya. Menurut pendapat Anda, tidak mungkin untuk mengelola penyebaran Rails dengan pipa aset tanpa capistrano atau serupa? Ini memalukan, untuk setup sederhana dulu bukan masalah besar untuk melakukannya dengan tangan.
jrochkind
Anda benar-benar membutuhkan Capistrano untuk Rails 3.1. Aset dikompilasi dalam direktori publik baru saat aplikasi lama Anda masih berjalan. Ketika kompilasi selesai dilakukan, versi baru disinkronkan dan server dihidupkan ulang secara otomatis.
Richard Hulse
"Untuk mendapatkan keuntungan maksimal dari jalur pipa dan sidik jari, Anda perlu mengatur header masa depan jauh di server web Anda, dan mengaktifkan kompresi gzip untuk file js dan css." - Bisakah Anda memberikan beberapa instruksi atau tautan untuk melakukan ini?
Isaac Betesh
7

Untuk memiliki lebih sedikit overhead dengan hal Pra-kompilasi.

Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/

Anda kemudian dapat menggunakan gambar dan stylesheet sebagai "/assets/stylesheet.css" di * .html.erb atau "/assets/web.png"

dbKooper
sumber
6

Bagi siapa pun yang menggunakan Heroku:

Jika Anda menerapkan ke Herkou, itu akan melakukan precompile untuk Anda secara otomatis selama penyebaran jika aset yang dikompilasi tidak termasuk (yaitu public/assetstidak berkomitmen) sehingga tidak perlu config.assets.compile = true, atau untuk melakukan aset yang dikompilasi.

Dokumen Heroku ada di sini . Sebuah CDN dianjurkan untuk menghapus beban pada sumber daya dyno.

William Denniss
sumber
1

Itu tidak akan sama dengan mengkompilasi, bahkan setelah hit pertama: karena file tidak ditulis ke sistem file, mereka tidak dapat dilayani secara langsung oleh server web. Beberapa kode ruby ​​akan selalu terlibat, meskipun hanya membaca entri cache.

Frederick Cheung
sumber
Hmm, saya berpikir bahwa dengan precompile=true, aset yang dikompilasi AKAN ditulis ke sistem file. Apakah kamu yakin Biarkan saya periksa ...
jrochkind
1
Bah, saya pikir Anda benar - mereka ADALAH ditulis ke sistem file, tetapi sepertinya di tmp/cachebukan public/assets, jadi bukan tempat yang bisa dilihat server web, mereka masih akan dilayani oleh aplikasi rel tidak server web. bla. apakah itu benar, menurut Anda?
jrochkind
Benar. Tidak akan secepat server web mengambilnya. Mungkin tidak masalah jika Anda meletakkan cdn seperti cloudfront di depan aplikasi Anda
Frederick Cheung
1

Set config.asset.compile = false

Tambahkan ke Gemfile Anda

group :assets do gem 'turbo-sprockets-rails3' end

Instal bundel

Lari rake assets:precompile

Kemudian Mulai server Anda

Mohammed Saleem
sumber
Sejauh yang saya set config.asset.compile = true in production.rbfile, karena tidak ada mekanisme pre-comple ditambahkan. Karena itu setiap kali kita memulai server, dibutuhkan terlalu banyak waktu untuk memuat halaman (Ketika permintaan mengenai memproses permintaan dan mengkompilasi aset). Sekarang saya termasuk turbo-sprockets-rails3dalam Gemfile dan menjalankan perintahnya rake assets:precompilemengkompilasi aset sebelumnya. Sekarang saya mengatur config.asset.compile = false in production.rbdan memulai server, pemuatan halaman tanpa penundaan. (Hanya memproses permintaan tanpa kompilasi aset)
Mohammed Saleem
2
Layak dikatakan bahwa turbo-sprockets-rails3hanya diperlukan di Ruby 3
Andre Figueiredo
0

Dari panduan resmi :

Pada permintaan pertama, aset dikompilasi dan di-cache sebagaimana diuraikan dalam pengembangan di atas, dan nama manifes yang digunakan dalam helper diubah untuk menyertakan hash MD5.

Sprockets juga mengatur header HTTP Kontrol-Cache ke maks-usia = 31536000. Ini menandakan semua cache antara server Anda dan browser klien bahwa konten ini (file yang dilayani) dapat di-cache selama 1 tahun. Efeknya adalah mengurangi jumlah permintaan untuk aset ini dari server Anda; aset memiliki peluang bagus untuk berada di cache browser lokal atau cache perantara.

Mode ini menggunakan lebih banyak memori, berkinerja lebih buruk daripada standar dan tidak direkomendasikan.

Juga, langkah precompile sama sekali tidak masalah jika Anda menggunakan Capistrano untuk penyebaran Anda. Itu mengurusnya untukmu. Kamu baru saja lari

cap deploy

atau (tergantung pada pengaturan Anda)

cap production deploy

dan Anda sudah siap. Jika Anda masih tidak menggunakannya, saya sangat merekomendasikan untuk memeriksanya.

Sergio Tulentsev
sumber
Jadi menurut Anda apakah bahasa dari panduan resmi itu sependapat dengan saya? Saya telah melihat panduan itu, saya tidak yakin apakah itu berarti apa yang saya sarankan di atas, bagaimana menurut Anda? Itu pertanyaan saya.
jrochkind
Ya, pada dasarnya Anda mengatakan hal yang sama. Saya sarankan agar Anda tidak mengaktifkan kompilasi langsung.
Sergio Tulentsev