js/css文件加载不上,求解
404 时, nginx 的日志为:
open() "xxxxx/public/assets/application.js" failed (2: No such file or directory
rails 的日志为:
ActionController::RoutingError (No route matches [GET] "/javascripts/application.js"):
unicorn 的日志为:
cache: [GET /javascripts/application.js] miss
production 配置 (局部,其他选项默认)为:
config.serve_static_assets = false
config.assets.compress = true
config.assets.compile = false
config.assets.digest = true
config.assets.debug = true
http://guides.rubyonrails.org/asset_pipeline.html 参考下这篇,部署到 production 前要 precompile 一下,还有注意下 js,css helper 的使用
config.assets.compile = false # 表示rails不会即时编译asset
ls public/assets # 不存在,表示你没有运行 bundle exec rake assets:precompile
config.serve_static_assets = false # 表示unicorn不处理静态文件
配置 nginx,让它来处理静态文件,在 server 节点增加:
# if the request is for a static resource, nginx should serve it directly
# and add a far future expires header to it, making the browser
# cache the resource and navigate faster over the website
# this probably needs some work with Rails 3.1's asset pipe_line
location ~ ^/(assets|images|javascripts|stylesheets|system)/ {
root /u/apps/your_project_name/current/public;
expires max;
break;
}
默认情况下,rails 会编译 application.js 和 application.css(作为入口),同时编译被 require 指令引用的文件 如果还有其他文件需要编译,则需要修改 config/environments/products.rb,例如:
config.assets.precompile += %w(
active_admin.js active_admin.css
)
昨晚已经跟着 asset_pipeline.html 里的指导做了 刚才又整理一下思路 1、在 development 下,assets pipeline 会尝试加载所有 controller 命名的 js 和 css。WEBrick 下的请求全部返回 200;unicorn 下的所有 controller 命名的全部 404,application/jquery 返回 200。 访问地址均 assets+ 文件名,例如/assets/application.js?body=1 2、在 production 下,assets pipeline 不会加载 controller 命名的 js 和 css。请求地址为“文件类型” + 文件名,例如/javascripts/application.js 和/stylesheets/application.css。注意,不是 assets 目录。
所以我想,解决这个问题的关键在于为什么 production 下会把路径转换为“文件类型 + 文件名”的形式,而不是“assets+ 文件名”的形式。product 下手动输入“assets+ 文件名”是可以访问的
搭车再多问一句,为什么 development 会加载 controller 的 js 而 production 不会
我的问题跟这个很像 http://stackoverflow.com/questions/7890845/rails-3-1-cant-enable-asset-pipeline-in-the-app
昨晚我也尝试了将 config.assets.enabled 设成 false,后来又改回 true。不确实是否跟这个有关系
yeah,解决了!
原因是我用了 mongoid,按照 mongoid 的要求,在 application.rb 中做了修改,注释 rails/all #require 'rails/all' require "action_controller/railtie" require "action_mailer/railtie" require "active_resource/railtie" require "rails/test_unit/railtie"
这个修改导致处理 assets pipeine 的 sprockets 没有被加载 因此解决方法是在后面追加一句 require 'sprockets/railtie'
刚刚摸索出一种比较省事的 config.assets.precompile 的写法,我是看了 sprockets 的 static_compiler.rb 的源码之后才发现的,现在我是这样写的(在 production.rb 里):
def compile_asset?(path)
if File.basename(path) =~ /^[^_].*\.\w+$/
puts "Compiling: #{path}"
true
else
puts "Ignoring: #{path}"
false
end
end
config.assets.precompile = [ method(:compile_asset?).to_proc ]
原理很简单,config.assets.precompile 可接受的类型包括 String,Regexp 和 Proc,但是 Rails 官方文档只提到前两个,还好自己去翻了源码 = =
#12 楼 里那个正则是针对 Compass 写的,在包含所有 css/js/图片 文件的前提下,排除 Compass 的 partials(文件名是下划线开头的,比如 _shared.css.sass)
不喜欢
config.assets.precompile += %w(
active_admin.js active_admin.css
)
这样的配置方式