Đường ray 4: nội dung không tải trong sản xuất


116

Tôi đang cố gắng đưa ứng dụng của mình vào sản xuất và đường dẫn nội dung hình ảnh và css không hoạt động.

Đây là những gì tôi hiện đang làm:

  • Nội dung hình ảnh có trong /app/assets/images/image.jpg
  • Biểu định kiểu có trong /app/assets/stylesheets/style.css
  • Trong bố cục của tôi, tôi tham chiếu tệp css như sau: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Trước khi khởi động lại unicorn, tôi chạy RAILS_ENV=production bundle exec rake assets:precompilevà nó thành công và tôi thấy các tệp dấu vân tay trong public/assetsthư mục.

Khi tôi duyệt đến trang web của mình, tôi gặp lỗi 404 not found for mysite.com/stylesheets/styles.css.

Tôi đang làm gì sai?

Cập nhật: Trong bố cục của tôi, nó trông như thế này:

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

Nguồn tạo là sau:

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

Có vẻ như Rails đang tìm kiếm các tệp css đã biên dịch không đúng cách. Nhưng thật khó hiểu tại sao nó lại hoạt động chính xác cho javascrip (hãy để ý /assets/****.jsđường dẫn).


Bạn có thể cho chúng tôi biết cách bạn tải tệp css của mình không? Có vẻ như do lỗi của bạn mà bạn cố gắng liên kết cứng nó hơn là sử dụng stylesheet_link_tag.
kik

1
Vừa được thêm ở trên. Tôi đang làm<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>
emersonthis

Được rồi, vì vậy tôi sẽ nhắc lại hai điều: 1. kiểm tra nguồn được tạo nếu dòng này được viết dưới dạng đường dẫn đến public/assetsvà 2. kiểm tra kỹ nếu không có hướng dẫn nào khác ở đâu đó đang cố gắng tải tệp css đó (có lẽ là được mã hóa cứng)
kik

Tôi không thể nói nếu sử dụng .erb là một vấn đề vì tôi không bao giờ làm như vậy: .home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }thực sự có thể được thay thế trong đĩa xích với .home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }. Có lẽ bạn có thể thử nếu điều này giúp ích.
kik

Bạn đang nói rằng tôi có thể làm cho tham chiếu đó trong tệp css của tôi động mà không cần thêm phần mở rộng .erb? Tôi đã thay đổi nó vì tôi không muốn liên kết bị phá vỡ khi tôi đang ở chế độ phát triển.
emersonthis

Câu trả lời:


105

Trong rails 4, bạn cần thực hiện các thay đổi dưới đây:

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

Điều này làm việc với tôi. sử dụng lệnh sau để biên dịch trước nội dung

RAILS_ENV=production bundle exec rake assets:precompile

May mắn nhất!


11
Tôi nghĩ rằng đặt config.assets.compile thành true sẽ giết chết hiệu suất trong sản xuất. còn nữa, css.erb? ai sử dụng cái đó? và những gì về sass và cà phê?
ahnbizcad

khi các tệp cà phê và sass được yêu cầu, chúng được xử lý bởi bộ xử lý được cung cấp bởi các viên đá quý coffee-script và sass-rails và sau đó được gửi trở lại trình duyệt dưới dạng JavaScript và CSS tương ứng.
Rameshwar Vyevhare

1
Vấn đề này đã được giải quyết cho Rails 4 và vì vậy không cần thiết phải sử dụng turbo-xích-rails3 đá quý
Rameshwar Vyevhare

4
Xin lỗi, tôi không thể kết nối những gì bạn đã nói để trả lời câu hỏi của tôi.
ahnbizcad

1
Thông thường, khi bạn chạy máy chủ sản xuất, bạn sẽ chạy Rails với hành khách hoặc kỳ lân hoặc puma phía sau máy chủ web Apache hoặc nginx. Tốt hơn là để Apache hoặc nginx phân phát các tệp tĩnh (js, css, hình ảnh) và máy chủ ứng dụng Rails (puma, unicorn) cung cấp mã và mẫu Rails. Để làm như vậy, bạn nên tắt config.serve_static_filesvà cấu hình bí danh trong Apache và nginx để xử lý assets.
Châu Hồng Lĩnh

85

Tôi vừa gặp sự cố tương tự và tìm thấy cài đặt này trong config / environment / production.rb:

# Rails 4:
config.serve_static_assets = false

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

Thay đổi nó để làm cho truenó hoạt động. Có vẻ như theo mặc định, Rails mong đợi bạn đã định cấu hình máy chủ web front-end của mình để xử lý các yêu cầu cho các tệp ngoài thư mục chung thay vì ủy quyền chúng cho ứng dụng Rails. Có lẽ bạn đã làm điều này cho các tệp javascript nhưng không phải các bảng định kiểu CSS của bạn?

( Xem tài liệu Rails 5 ). Như đã lưu ý trong phần nhận xét, với Rails 5, bạn có thể chỉ cần đặt RAILS_SERVE_STATIC_FILESbiến môi trường, vì cài đặt mặc định là config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.


1
CẢNH BÁO DEPRECATION: Tùy chọn cấu hình config.serve_static_assetsđã được đổi tên để config.serve_static_fileslàm rõ vai trò của nó (nó chỉ cho phép cung cấp mọi thứ trong publicthư mục và không liên quan đến đường dẫn nội dung). Các serve_static_assetsbí danh sẽ được loại bỏ trong Rails 5.0. Vui lòng di chuyển các tệp cấu hình của bạn cho phù hợp.
yekta

Trước đây khi tôi gặp phải vấn đề này, việc thay đổi dòng đó đã giải quyết được nó cho tôi, nhưng bây giờ tôi lại phải đối mặt với nó (tôi không biết làm thế nào tôi tiếp tục kết thúc trong những tình huống này.) Và điều này là chưa đủ. Bất kỳ gợi ý nào nữa về những gì có thể sai?
Toàn bộ

2
Đây phải là câu trả lời được chấp nhận. Mặc dù nó có config.serve_static_filestrong Rails 4.2config.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 chứa config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?để bạn có thể thiết lập điều này khác cho môi trường của mình mà không cần thay đổi mã đã đăng ký vào SCM của bạn.
tobinjim

Để kích hoạt nó: "export RAILS_SERVE_STATIC_FILES =" sau đó bạn chạy "rails s -e production" Để tắt nó: "unset RAILS_SERVE_STATIC_FILES"
Alfredo Osorio

32

Trong /config/environments/production.rbtôi đã phải thêm điều này:

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

.Js đã được biên dịch trước, nhưng tôi đã thêm nó. .Css và .css.erb dường như không tự động xảy ra. Loại ^[^_]trừ các thành phần được biên dịch - đó là một regexp.

Có một chút bực bội khi tài liệu nói rõ rằng đường ống nội dung IS được bật theo mặc định nhưng không làm rõ thực tế là chỉ áp dụng cho javascrip.


Bạn cần phải thêm styles.css để config.assets.precompile
Frederick Cheung

23

Tôi đã có thể giải quyết vấn đề này bằng cách thay đổi: config.assets.compile = falsethành
config.assets.compile = truetrong/config/environments/production.rb

Cập nhật (ngày 24 tháng 6 năm 2018) : Phương pháp này tạo ra lỗ hổng bảo mật nếu phiên bản Sprockets bạn đang sử dụng nhỏ hơn 2.12.5, 3.7.2 hoặc 4.0.0.beta8


7
Điều này không có nghĩa là Rails đang biên dịch các nội dung thay vì tải chúng từ CDN?
Benjamin Oakes

@BenjaminOakes Vâng, và đó là những gì tôi muốn
Yanofsky

2
Chế độ này sử dụng nhiều bộ nhớ hơn, hoạt động kém hơn so với mặc định và không được khuyến khích. Tốt hơn nên sử dụng proxy nginx.
yekta

16

Đối với Rails 5, bạn nên bật mã cấu hình sau:

config.public_file_server.enabled = true

Theo mặc định, Rails 5 vận chuyển với dòng cấu hình sau:

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

Do đó, bạn sẽ cần đặt biến môi trường RAILS_SERVE_STATIC_FILESthành true.


1
Đối với Rails 5, tôi nên thêm, tôi đã đặt passenger_env_var RAILS_SERVE_STATIC_FILES true;khối vị trí của ứng dụng trong tệp nginx.conf của mình.
Martin Velez

10

Có 2 điều bạn phải hoàn thành để phục vụ tài sản trong quá trình sản xuất:

  1. Biên dịch trước các nội dung.
  2. Cung cấp nội dung trên máy chủ cho trình duyệt.

1) Để biên dịch trước nội dung, bạn có một số lựa chọn.

  • Bạn có thể chạy rake assets:precompiletrên máy cục bộ của mình, cam kết nó với điều khiển mã nguồn (git), sau đó chạy chương trình triển khai, ví dụ capistrano. Đây không phải là một cách tốt để cam kết tài sản được biên dịch trước cho SCM.

  • Bạn có thể viết một tác vụ rake chạy RAILS_ENV=production rake assets:precompiletrên các máy chủ mục tiêu mỗi khi bạn triển khai ứng dụng Rails của mình vào phiên bản sản xuất, trước khi bạn khởi động lại máy chủ.

Mã trong một nhiệm vụ cho capistrano sẽ giống như sau:

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) Bây giờ, bạn có tài sản trên máy chủ sản xuất, bạn cần cung cấp chúng cho trình duyệt.

Một lần nữa, bạn có một số lựa chọn.

  • Bật phân phát tệp tĩnh Rails trong config / environment / production.rb

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

    Sử dụng Rails để cung cấp các tệp tĩnh sẽ giết chết hiệu suất ứng dụng Rails của bạn.

  • Định cấu hình nginx (hoặc Apache) để cung cấp các tệp tĩnh.

    Ví dụ: nginx của tôi đã được định cấu hình để hoạt động với Puma trông như sau:

    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 không còn tạo phiên bản không có dấu vân tay của nội dung: stylesheets / style.css sẽ không được tạo cho bạn.

Nếu bạn sử dụng stylesheet_link_tagthì liên kết chính xác đến biểu định kiểu của bạn sẽ được tạo

Ngoài ra, styles.cssphải có trong config.assets.precompileđó là danh sách những thứ đã được biên dịch trước


Tôi thấy tệp có dấu vân tay trong thư mục / public / asset /. Trong bố cục của tôi, tôi có điều này: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>Điều này không chính xác? '
emersonthis

Vì một số lý do, việc triển khai sản xuất vẫn trỏ đến các tệp gốc khi tôi xem nguồn <link data-turbolinks-track="true" href="https://stackoverflow.com/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />Nhưng các tệp javascript là chính xác! Tôi không hiểu tại sao các cấu hình giống nhau lại hoạt động cho các tệp .js nhưng không hoạt động với .css.
emersonthis

Trên Rails 5.0.0.beta3, tôi nhận được cảnh báo này: CẢNH BÁO DEPRECATION: serve_static_fileskhông được dùng nữa và sẽ bị xóa trong Rails 5.1. Hãy sử dụng public_file_server.enabled = truethay thế.
GMA

@emersonthis Tương tự! Js tải hoàn hảo nhưng một số tệp css bị lỗi 404. Bạn đã giải quyết điều này?
IvRRimUm

Nó gần như LUÔN là một vấn đề với cấu hình đường ống nội dung. Nếu bạn có tệp ở bất kỳ vị trí nào không phải là vị trí mặc định, thì đó gần như chắc chắn là vấn đề và bạn cần phải thông báo cho đường dẫn nội dung về nó bằng cách sử dụng một cái gì đó giống như câu trả lời đầu tiên.
emersonthis

3

thay đổi dòng tệp Production.rb của bạn

config.assets.compile = false

thành

config.assets.compile = true

và cũng thêm

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

tại sao phải biên dịch? chúng tôi arent giả để biên dịch đối với sản xuất trong khi nó đang chạy
James Tân

1
KHÔNG BAO GIỜ LÀM ĐIỀU NÀY! Bất kỳ ai đặt config.assets.compile thành true trong sản xuất đều phải được sử dụng.
bkunzi01

2

Tôi đang chạy Ubuntu Server 14.04 , Ruby 2.2.1Rails 4.2.4 Tôi đã theo dõi trình tự triển khai từ DigitalOcean và mọi thứ diễn ra tốt đẹp nhưng khi tôi truy cập trình duyệt và nhập địa chỉ IP của VPS của mình, ứng dụng của tôi được tải nhưng không có phong cách và javascript.

Ứng dụng đang chạy với UnicornNginx . Để khắc phục sự cố này, tôi đã nhập máy chủ của mình bằng SSH với ' người triển khai' người dùng của tôi và đi tới đường dẫn ứng dụng của tôi là '/ home / deployer / apps / blog' và chạy lệnh sau:

RAILS_ENV=production bin/rake assets:precompile

Sau đó, tôi chỉ cần khởi động lại VPS và thế là xong! Nó hoạt động cho tôi!

Hy vọng nó có thể hữu ích cho người khác!


2

Nếu biên dịch trước được đặt, bạn KHÔNG cần

config.assets.compile = true

vì điều này là để cung cấp nội dung trực tiếp.

Vấn đề của chúng tôi là chúng tôi chỉ có cơ sở khóa bí mật phát triển được đặt trong config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

Cần đầu vào cho môi trường sản xuất


1
như đã đề cập trong câu trả lời khác mà bạn cần config.assets.precompile = ['*.js', '*.css', '*.css.erb'] và để chạyRAILS_ENV=production bundle exec rake assets:precompile
xxjjnn

1
này cho phép biên soạn các tài sản trong khi trực tiếp trên sản xuất, rất chậm, không đúng
James Tân

2

Những gì bạn KHÔNG NÊN làm:

Một số đồng nghiệp của tôi ở trên đã khuyến nghị bạn làm điều này:

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

Đường dẫn tài sản đường ray nói về cách tiếp cận trên:

Chế độ này sử dụng nhiều bộ nhớ hơn, hoạt động kém hơn so với mặc định và không được khuyến khích. Xem tại đây: ( http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation )

Những gì bạn NÊN làm:

Biên dịch trước nội dung của bạn.

RAILS_ENV=production rake assets:precompile

Bạn có thể làm điều đó với một nhiệm vụ cào.


Tại sao lại thêm đồ tạo tác xây dựng vào git? Bạn chỉ có thể thêm nhiệm vụ cào để quá trình xây dựng của bạn và tránh gitspam lớn (đặc biệt là nếu bạn có uglifier và gzipping trên, mà bạn nên)
Dr.Strangelove

@ Dr.Strangelove Cảm ơn bạn đã nhận xét - Tôi không biết đủ về điều đó -: bạn có thể giải thích / chỉnh sửa bài gốc không?
BKSpurgeon

1

Trình so khớp mặc định để biên dịch tệp bao gồm application.js, application.css và tất cả các tệp không phải JS / CSS (điều này sẽ tự động bao gồm tất cả nội dung hình ảnh) từ các thư mục ứng dụng / nội dung bao gồm đá quý của bạn:

Nếu bạn có các tệp kê khai khác hoặc bảng định kiểu riêng lẻ và tệp JavaScript để bao gồm, bạn có thể thêm chúng vào mảng biên dịch trước trong 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

Trước hết, hãy kiểm tra nội dung của bạn, có thể có một số lỗi trong quá trình biên dịch trước nội dung.

Để biên dịch trước nội dung trong phiên bản sản xuất, hãy chạy lệnh này:

RAILS_ENV=production rake assets:precompile

Nếu nó hiển thị lỗi, hãy xóa nó trước,

Trong trường hợp lỗi "biến không xác định", hãy tải tệp biến đó trước khi sử dụng nó trong tệp khác.

thí dụ:

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

trong tập tin application.rb trình tự đối chiếu trước các nội dung

thí dụ:

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

Tìm thấy cái này:

Tùy chọn cấu hình config.serve_static_assetsđã được đổi tên config.serve_static_filesđể làm rõ vai trò của nó.

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

Vì vậy, hãy đặt env RAILS_SERVE_STATIC_FILEShoặc using Nginxđể phục vụ các tệp tĩnh. Thêm config.serve_static_assets = truesẽ vẫn hoạt động, nhưng bị xóa trong tương lai.


1

không nên để capistrano biên dịch trước nội dung, vì có thể mất nhiều thời gian và thường hết thời gian. cố gắng biên dịch trước nội dung cục bộ.

Đầu tiên, thiết lập trong config / application.rb, config.assets.initialize_on_precompile = false sau đó thực hiện cục bộ RAILS_ENV=production bin/rake assets:precompile và thêm công khai / tài sản đó vào git.

và config / environment / development.rb, thay đổi đường dẫn nội dung của bạn để tránh sử dụng các nội dung được biên dịch trước:

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

Nếu bạn gặp sự cố kết nối db, nghĩa là bạn có bộ khởi tạo sử dụng db. một cách xung quanh đó là thiết lập một môi trường mới bằng cách sao chép production.rb có thể là production2 .rb và trong database.yml, thêm môi trường production2 với sự phát triển cài đặt db. sau đó làm

RAILS_ENV=production2 bin/rake assets:precompile

nếu bạn vẫn gặp một số vấn đề với nội dung, ví dụ như ckeditor, hãy thêm tệp js vào config / initializers / asset.rb

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


0

Tôi có thể sai nhưng những người khuyên bạn nên thay đổi

config.assets.compile = true

Nhận xét về dòng này có nội dung: # Không dự phòng cho quy trình nội dung nếu nội dung được biên dịch trước bị bỏ lỡ.

Điều này cho thấy rằng bằng cách đặt điều này thành true, bạn không khắc phục được sự cố mà là bỏ qua nó và chạy đường ống mọi lúc. Điều này chắc chắn phải giết chết hiệu suất của bạn và đánh bại mục đích của đường ống?

Tôi cũng gặp lỗi này và đó là do ứng dụng đang chạy trong một thư mục con mà rails không biết.

Vì vậy, tệp css của tôi ở trong home / subfolder / app / public / .... nhưng rails lại tìm kiếm trong home / app / public / ...

hãy thử di chuyển ứng dụng của bạn ra khỏi thư mục con hoặc nói với đường ray rằng nó nằm trong một thư mục con.


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

Điều này đã khắc phục sự cố cho tôi trong quá trình sản xuất. Đặt nó vào cấu hình nginx.


0

Ngay cả khi chúng tôi phải đối mặt với cùng một vấn đề, nơi RAILS_ENV=production bundle exec rake assets:precompileđã thành công nhưng mọi thứ không diễn ra như mong đợi.
Chúng tôi phát hiện ra rằng kỳ lân là thủ phạm chính ở đây.

Tương tự như trường hợp của bạn, thậm chí chúng tôi đã từng khởi động lại unicorn sau khi biên dịch nội dung. Người ta nhận thấy rằng khi kỳ lân được khởi động lại, chỉ có các quy trình công nhân của nó được khởi động lại chứ không phải quy trình chính.
Đây là lý do chính khiến nội dung chính xác không được phân phát.

Sau đó, sau khi biên dịch nội dung, chúng tôi đã dừng và khởi động kỳ lân để quá trình tổng thể kỳ lân cũng được khởi động lại và các nội dung chính xác đang được phân phát.
Dừng và khởi động kỳ lân mang lại khoảng 10 giây thời gian chết so với khởi động lại kỳ lân. Đây là cách giải quyết có thể được sử dụng khi giải pháp lâu dài là chuyển sang puma từ kỳ lân.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.