Rails 4:资产未在生产中加载

Posted

技术标签:

【中文标题】Rails 4:资产未在生产中加载【英文标题】:Rails 4: assets not loading in production 【发布时间】:2013-09-13 01:25:25 【问题描述】:

我正在尝试将我的应用程序投入生产,但图像和 css 资产路径无法正常工作。

这是我目前正在做的事情:

图片资源位于 /app/assets/images/image.jpg 样式表位于 /app/assets/stylesheets/style.css 中 在我的布局中,我引用了这样的 css 文件:<%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %> 在重启独角兽之前,我运行RAILS_ENV=production bundle exec rake assets:precompile,它成功了,我在public/assets目录中看到了指纹文件。

当我浏览我的网站时,我收到 mysite.com/stylesheets/styles.css 的 404 not found 错误。

我做错了什么?

更新: 在我的布局中,它看起来像这样:

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

生成源是这样的:

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

Rails 似乎没有正确查找编译后的 css 文件。但它非常令人困惑为什么它在 javascripts 中正常工作(注意 /assets/****.js 路径)。

【问题讨论】:

你能告诉我们你是如何加载你的css文件的吗?从您的错误看来,您尝试硬链接它而不是使用stylesheet_link_tag 刚刚添加到上面。我在做&lt;%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" =&gt; true %&gt; 好的,所以我会推荐两件事:1. 如果此行被写为public/assets 的路径,请检查生成的源代码;以及 2. 仔细检查是否没有其他指令试图加载它css 文件(可能是硬编码的) 我不能说使用 .erb 是否有问题,因为我从不这样做:.home background: #FFF url(&lt;%= image_path 'hippopotamus.jpg' %&gt;) no-repeat; 实际上可以在 sprocket 中替换为 .home background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; 。如果这有帮助,也许你可以试试。 您是说我可以在我的 css 文件中动态引用该引用而不添加 .erb 扩展名?我更改了它,因为我不希望在我处于开发模式时链接断开。 【参考方案1】:

Rails 4 不再生成资产的非指纹版本:不会为您生成 stylesheets/style.css。

如果您使用stylesheet_link_tag,则会生成指向您的样式表的正确链接

另外styles.css 应该在config.assets.precompile 中,这是预编译的东西的列表

【讨论】:

我在 /public/assets/ 目录中看到了指纹文件。在我的布局中,我有这个:&lt;%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" =&gt; true %&gt; 这是不正确的吗?` 由于某种原因,当我查看源代码时,生产部署仍然指向原始文件&lt;link data-turbolinks-track="true" href="/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" /&gt;但是javascript文件是正确的!我不明白为什么相同的配置适用于 .js 文件而不适用于 .css。 在 Rails 5.0.0.beta3 上我收到此警告:弃用警告:serve_static_files 已弃用,将在 Rails 5.1 中删除。请改用public_file_server.enabled = true @emersonthis 一样! Js 加载完美,但一些 css 文件得到404。你解决了吗? 资产管道配置几乎总是有问题。如果您在任何非默认位置有文件,那几乎肯定是问题所在,您需要使用第一个答案之类的方式告诉资产管道。【参考方案2】:

/config/environments/production.rb 我必须添加这个:

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

.js 已经被预编译了,但我还是添加了它。 .css 和 .css.erb 显然不会自动发生。 ^[^_] 排除了部分编译——它是一个正则表达式。

有点令人沮丧的是,文档明确指出默认启用资产管道,但没有阐明仅适用于 javascripts 的事实。

【讨论】:

需要在config.assets.precompile中添加styles.css【参考方案3】:

我能够通过更改来解决这个问题: config.assets.compile = falseconfig.assets.compile = true/config/environments/production.rb

更新(2018 年 6 月 24 日):如果您使用的 Sprocket 版本低于 2.12.5、3.7.2 或 4.0.0.beta8,此方法会创建 a security vulnerability

【讨论】:

这是否意味着 Rails 正在编译资产,而不是从 CDN 加载它们? @BenjaminOakes 是的,这就是我想要的 此模式使用更多内存,性能比默认更差,不推荐使用。最好使用 nginx 代理。【参考方案4】:

在 Rails 4 中,您需要进行以下更改:

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

这对我有用。使用以下命令预编译资产

RAILS_ENV=production bundle exec rake assets:precompile

祝你好运!

【讨论】:

我认为将 config.assets.compile 设置为 true 会降低生产性能。还有,css.erb?谁用它?萨斯和咖啡呢? 当请求 coffee 和 sass 文件时,它们由 coffee-script 和 sass-rails gems 提供的处理器处理,然后分别作为 JavaScript 和 CSS 发送回浏览器。 Rails 4 已经解决了这个问题,所以不需要使用 turbo-sprocket-rails3 gem 抱歉,我无法将您回答我的问题的内容联系起来。 通常,当您运行生产服务器时,您将在 Apache 或 nginx 网络服务器后面运行带有乘客或独角兽或美洲狮的 Rails。最好让 Apache 或 nginx 服务静态文件(js、css、图像),而 Rails 应用服务器(puma、unicorn)服务 Rails 代码和模板。为此,您应该关闭config.serve_static_files,并在Apache和nginx中配置别名来处理assets【参考方案5】:

我刚遇到同样的问题,在 config/environments/production.rb 中找到了这个设置:

# Rails 4:
config.serve_static_assets = false

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

将其更改为 true 即可正常工作。默认情况下,Rails 似乎希望您已将前端 Web 服务器配置为处理公共文件夹外的文件请求,而不是将它们代理到 Rails 应用程序。也许您已经为您的 javascript 文件而不是您的 CSS 样式表做到了这一点?

(See Rails 5 documentation)。如 cmets 中所述,在 Rails 5 中,您可以只设置 RAILS_SERVE_STATIC_FILES 环境变量,因为默认设置是 config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

【讨论】:

弃用警告:配置选项 config.serve_static_assets 已重命名为 config.serve_static_files 以阐明其作用(它仅支持为 public 文件夹中的所有内容提供服务,并且与资产管道无关)。 serve_static_assets 别名将在 Rails 5.0 中删除。请相应地迁移您的配置文件。 早些时候当我面临这个问题时,改变那条线已经为我解决了它,但现在我又面临它了(我不知道我是如何一直在这些情况下结束的。)而且这个还不够。关于可能出了什么问题还有什么建议吗? 这应该是公认的答案。虽然它是 Rails 4.2 中的 config.serve_static_files 和 Rails 5 中的 config.public_file_server.enabled。 @见github.com/heroku/rails_serve_static_assets/blob/master/lib/… Rails 5.0.0.1 config/environments/production.rb 包含config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?,因此您可以为您的环境进行不同的设置,而无需更改签入 SCM 的代码。 启用它:"export RAILS_SERVE_STATIC_FILES=" 然后你运行 "rails s -e production" 禁用它:"unset RAILS_SERVE_STATIC_FILES"【参考方案6】:

用于编译文件的默认匹配器包括 app/assets 文件夹中的 application.js、application.css 和所有非 JS/CSS 文件(这将自动包括所有图像资产):

如果您有其他清单或单独的样式表和 JavaScript 文件要包含,您可以将它们添加到 config/initializers/assets.rb 中的预编译数组中:

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

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

【讨论】:

【参考方案7】:

我正在运行 Ubuntu Server 14.04Ruby 2.2.1Rails 4.2.4 我已关注部署 turorial from DigitalOcean 和一切顺利,但是当我进入浏览器并输入我的 VPS 的 IP 地址时,我的应用程序已加载但没有样式和 javascript。

该应用使用 UnicornNginx 运行。为了解决这个问题,我使用 SSH 和我的用户 'deployer' 进入我的服务器,然后转到我的应用路径 '/home/deployer/ apps/blog' 并运行以下命令:

RAILS_ENV=production bin/rake assets:precompile

然后我只需重新启动 VPS 就可以了! 它对我有用!

希望它对其他人有用!

【讨论】:

【参考方案8】:

更改您的 Production.rb 文件行

config.assets.compile = false

进入

config.assets.compile = true

还有添加

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

【讨论】:

为什么要编译?我们不假设在运行时在生产环境中编译 永远不要这样做!任何在生产环境中将 config.assets.compile 设置为 true 的人都应该被枪决。【参考方案9】:

如果设置了预编译,则不需要

config.assets.compile = true

因为这是为了实时提供资产。

我们的问题是我们只在config/secrets.yml 中设置了开发密钥库

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

生产环境需要入口

【讨论】:

如其他答案中所述,您需要config.assets.precompile = ['*.js', '*.css', '*.css.erb'] 并运行RAILS_ENV=production bundle exec rake assets:precompile 这可以在生产时编译资产,非常慢,不对【参考方案10】:

首先检查您的资产,可能在预编译资产时出现一些错误。

要在生产环境中预编译资产,请运行以下命令:

RAILS_ENV=production rake assets:precompile

如果显示错误,请先删除,

如果出现“未定义变量”错误,请先加载该变量文件,然后再将其用于另一个文件。

示例:

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

在application.rb文件中设置资产预编译顺序

示例:

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

【讨论】:

【参考方案11】:

找到这个:

配置选项config.serve_static_assets 已重命名为config.serve_static_files 以明确其作用。

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?

所以设置 env RAILS_SERVE_STATIC_FILES 或使用 Nginx 来提供静态文件。 添加 config.serve_static_assets = true 仍然可以使用,但以后会删除。

【讨论】:

【参考方案12】:

要在生产环境中为资产服务,您必须完成 2 件事:

    预编译资产。 将服务器上的资产提供给浏览器。

1) 为了预编译资产,您有多种选择。

您可以在本地计算机上运行 rake assets:precompile,将其提交到源代码控制 (git),然后运行部署程序,例如 capistrano。这不是向 SCM 提交预编译资产的好方法。

您可以编写一个 rake 任务,在每次将 Rails 应用部署到生产环境时在目标服务器上运行 RAILS_ENV=production rake assets:precompile,然后重新启动服务器。

capistrano 任务中的代码类似于以下内容:

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) 现在,您拥有生产服务器上的资产,您需要将它们提供给浏览器。

同样,您有多种选择。

config/environments/production.rb

中开启 Rails 静态文件服务
config.serve_static_assets = true # old

or

config.serve_static_files = true # new

使用 Rails 提供静态文件会降低 Rails 应用程序的性能。

配置 nginx(或 Apache)以提供静态文件。

例如,我配置为与 Puma 一起使用的 nginx 如下所示:

location ~ ^/(assets|images|fonts)/(.*)$ 
    alias /var/www/foster_care/current/public/$1/$2;
    gzip on;
    expires max;
    add_header Cache-Control public;

【讨论】:

【参考方案13】:

对于 Rails 5,您应该启用以下配置代码:

config.public_file_server.enabled = true

默认情况下,Rails 5 附带以下配置:

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

因此,您需要将环境变量RAILS_SERVE_STATIC_FILES 设置为true。

【讨论】:

对于 Rails 5,我应该添加,我在 nginx.conf 文件的应用程序的位置块中设置了passenger_env_var RAILS_SERVE_STATIC_FILES true;【参考方案14】:

我可能错了,但是那些建议改变的人

config.assets.compile = true

这一行的注释是:#Do not fallback to assets pipeline if a precompiled assets is missing.

这表明,通过将此设置为 true,您并没有解决问题,而是绕过它并每次运行管道。这肯定会扼杀你的表现并破坏管道的目的吗?

我遇到了同样的错误,这是由于应用程序在 rails 不知道的子文件夹中运行。

所以我的 css 文件在 home/subfolder/app/public/.... 但 rails 正在寻找 home/app/public/...

尝试将您的应用移出子文件夹或告诉 rails 它位于子文件夹中。

【讨论】:

【参考方案15】:

不建议让 capistrano 进行资产预编译,因为它可能需要很长时间并且经常超时。尝试做本地资产预编译。

1st,在 config/application.rb 中设置 config.assets.initialize_on_precompile = false 然后做本地 RAILS_ENV=production bin/rake assets:precompile 并将这些公共/资产添加到 git。

和config/environments/development.rb,改变你的资产路径以避免使用预编译资产:

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

如果您有 db 连接问题,则意味着您有使用 db 的初始化程序。一种解决方法是通过将 production.rb 复制为 production2.rb 来设置新环境,并在 database.yml 中添加 production2 环境和 development 数据库设置。然后做

RAILS_ENV=production2 bin/rake assets:precompile

如果您仍然面临资产问题,例如 ckeditor, 将js文件添加到config/initializers/assets.rb

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

【讨论】:

【参考方案16】:
location ~ ^/assets/ 
  expires 1y;
  add_header Cache-Control public;
  add_header ETag "";

这解决了我在生产中的问题。将其放入 nginx 配置中。

【讨论】:

【参考方案17】:

即使我们遇到了同样的问题,RAILS_ENV=production bundle exec rake assets:precompile 成功但事情没有按预期工作。 我们发现独角兽是这里的罪魁祸首。

与您的情况相同,即使我们曾经在编译资产后重新启动独角兽。注意到当独角兽重启时,只有它的工作进程被重启,而主进程没有被重启。 这是未提供正确资产的主要原因。

后来,在编译完资产后,我们停止并启动了 unicorn,这样 unicorn 主进程也重新启动,并提供了正确的资产。 与重启独角兽相比,停止和启动独角兽会带来大约 10 秒的停机时间。当长期解决方案从独角兽转移到 puma 时,这是可以使用的解决方法。

【讨论】:

【参考方案18】:

你不应该做的事情:

上面的一些同事建议你这样做:

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

rails 资产管道说明了上述方法:

此模式使用更多内存,性能比默认模式更差,不推荐使用。见这里:(http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation)

你应该做什么:

预编译您的资产。

RAILS_ENV=production rake assets:precompile

您可能可以通过 rake 任务来做到这一点。

【讨论】:

为什么要将构建工件添加到 git 中?您可以在构建过程中添加 rake 任务并避免大量 gitspam(特别是如果您有 uglifier 和 gzipping,您应该这样做) @Dr.Strangelove 谢谢你的评论 - 我对此了解不够 - :你能详细说明/编辑原始帖子吗?

以上是关于Rails 4:资产未在生产中加载的主要内容,如果未能解决你的问题,请参考以下文章

Rails 应用程序未在弹性 beantalk aws 上加载资产

Rails 不会在生产模式下加载我的图像资产

ckeditor gem custom config.js 未在生产中加载

在 Rails 4 生产环境中找不到资产的 404 错误

Rails 4 - 在生产服务器上预编译资产后没有 manifest.json

在生产中加载webpacker资产