javascript_include_tag在Rails 4中在生产环境下生成"/javascripts/"而不是"/assets"

36

我有一个使用Rails 4的应用程序

<%= javascript_include_tag "modernizr", "data-turbolinks-track" => true %>

在开发中,以下 HTML 被渲染,并加载了 modernizr:

<script data-turbolinks-track="true" src="/assets/modernizr.js?body=1"></script>

在生产环境中,以下HTML会被呈现,并且modernizr未能加载(404未找到):

In production, the followign HTML is rendered, and modernizr is not loaded (404 not found):

<script data-turbolinks-track="true" src="/javascripts/modernizr.js"></script>

在生产环境中,可以找到并浏览 /assets/modernizr.js

Rails文档指出,javascript_include_tag应该生成

<script data-turbolinks-track="true" src="/assets/modernizr.js?body=1"></script>
在生产环境中,我的stylesheet_link_tag链接到/assets/目录,一切正常。但为什么javascript_include_tag在生产环境中链接到/javascripts而不是/assets,我该如何修复它?

3
你找到解决办法了吗?我遇到了完全相同的问题,但这里的回答都没有帮助。 - gregoltsov
2
在生产环境中,您应该拥有一个指纹化的资产URL,例如/assets/light-0cd9377b97b67182b68c8023bd6c2fbe.css - phoet
2
这是一个干净的Rails 4应用程序,还是从早期的Rails版本升级而来的? - Greg Dan
5个回答

24

AssetUrlHelper的用法之一指出它将生成类似于以下内容的/javascripts/ url:

# asset_path "application", type: :javascript # => /javascripts/application.js

(来自asset_url_helper.rb第117行 - [1])

这段代码看起来只有在编译后的asset不存在时才会被执行, 因此似乎您的asset编译不起作用(当发生这种情况时,我的部署通常会失败,所以也许您的部署并没有运行)。

同样的asset_url_helper.rb将/javascripts/部分称为“extname”, 并使用以下映射来知道如何生成名称:

 # Maps asset types to public directory.
  ASSET_PUBLIC_DIRECTORIES = {
    audio:      '/audios',
    font:       '/fonts',
    image:      '/images',
    javascript: '/javascripts',
    stylesheet: '/stylesheets',
    video:      '/videos'
  }

一个新的Rails 4应用程序在config/environments/production.rb文件中有这个设置:

  # Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false

看起来似乎与您所看到的行为相匹配。


4
谢谢!一些 JS/CSS 文件没有预编译,因为它们无法与 application.js/css 文件关联,所以 Rails 4 资产预编译找不到这些文件。您可以将该文件添加到预编译文件列表中,如下所示:#config/environments/production.rb config.assets.precompile += [ Proc.new {|path| File.basename(path) =~ /^[^_].*\.\w+$/} ] - comme
4
Rails 的资产管道似乎有一些非常糟糕的默认设置。 - jeffcook2150

12

默认情况下,Rails 仅预编译 application.jsapplication.css 和在 assets 路径下找到的任何图像。因此,在生产环境中,modernizr 将不会被预编译,因此 JavaScript 助手将无法找到该文件。

为了解决这个问题,您可以通过修改 production.rb 中的以下配置列表,将 modernizr 添加到预编译列表中。

config.assets.precompile += ['modernizr.js']

了解更多信息请参见 Rails 指南


这个答案是正确的。在生产环境中,如果 javascript_include_tag 在搜索路径(我认为是 ./public/assets/)中找不到预编译的 JavaScript 资源,它将生成以 /javascripts/ 开头的 src(Rails 认为您会将该资源放在 ./public/javascripts/ 中)。在开发环境中,config.assets.compile 设置为 true,因此如果 javascript_include_tag./public/assets 中找不到资源,Rails 将编译资源,然后找到它。在生产环境中,config.assets.compilefalse。因此,请使用 config.assets.precompile 确保您的资产已经预编译。 - Hong

4

但是这只是将资源编译到 public/assets/ 文件夹中 - 它并未解释为什么路径生成不正确。 - gregoltsov
你在 production.rb 中更改了路径吗?它看起来像是 config.assets.prefix = "/some_other_path"。http://guides.rubyonrails.org/asset_pipeline.html#changing-the-assets-path - Ross Allen
不,我没有。我的 vendor/ 文件夹里的所有资源都能被正确地编译到 /assets 文件夹中,并且这些资源的路径也是正确的。只是位于 /app/assets 文件夹下的 JavaScript 文件在使用 javascript_include_tag 生成路径时出现了错误。是的,我已经将它们添加到了 precompile 中。这真是一种奇怪的行为…… - gregoltsov

1

我有一个使用Rails 4开发的新应用程序,部署在Heroku上:

<%= javascript_include_tag "application", "data-turbolinks-track" => true %>

我的JavaScript应用程序(fingerprint).js从src:assets/application.js调用。

我认为你的问题来自于production.rb中定义了另一个位置的资产。

因此,您可以在config/production.rb中添加Moderniz.js:

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

或者只需将modernizr脚本添加到您的application.js中:

//= require modernizr

并删除您的布局中的modernizr脚本调用。

<%= javascript_include_tag "modernizr", "data-turbolinks-track" => true %>

你能检查一下在生产环境中,你的application.js文件是从哪里提供的吗?

-1

这可能是因为该文件需要位于/vendor/assets/javascript而不是/app/assets/javascript。Vendor文件夹用于JavaScript库,而App文件夹用于您的代码。

比添加标签到布局更好的解决方案是将脚本引用添加到您的application.js中,并让Sass编译器压缩并附加到您的主JavaScript文件中。

如果您没有得到明确的答案,请查看: http://guides.rubyonrails.org/asset_pipeline.html#asset-organization


/vendor/assets/javascript//app/assets/javascript/ 文件夹中的文件都会被编译到 public/assets/ 文件夹中,生成的 manifest.json 文件描述了查找指纹文件的逻辑路径。但是,为了使其正常工作,javascript_include_tag 生成的路径仍然需要指向 assets/ - gregoltsov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接