Rails 第三方引入 js 后 production 下报未编译的错误

piginzoo · 2012年02月25日 · 最后由 sunshineboy 回复于 2016年06月29日 · 6329 次阅读

生产部署中遇到一个问题,希望高手帮忙看看?

我在某个单独页面内引入了一个第三方的 js,我没有把它 include 到 application.js 中,因为我觉得只有这一个页面用,不能放到 application.js 中。

于是乎,我就在这个单独页面中加入了这行: <%= javascript_include_tag "jquery.fancybox-1.3.4" %>

开发环境一切 ok,到了生产部署的时候,就报错啦: ActionView::Template::Error (jquery.fancybox-1.3.4 isn't precompiled): 1: <%= javascript_include_tag "jquery.fancybox-1.3.4" %>

当然先问 google 大神+stackoverflow 大神,巴拉巴拉,得到了一堆的指导,屁如:

  1. 在 production.rb 中加入预编译文件列表 #加入我们自己额外用哦 js 的预编译 config.assets.precompile += %w( jquery.fancybox-1.3.4.js )

2.去人肉到生产环境下检查 cap deploy 是否生成了编译后的 js,果然,也找到了

# ll public/assets/jquery.fancybox-1.3.4*
public/assets/jquery.fancybox-1.3.4-9d272ff223e751fc8890a84ebfc51814.js
public/assets/jquery.fancybox-1.3.4-9d272ff223e751fc8890a84ebfc51814.js.gz
public/assets/jquery.fancybox-1.3.4.js
public/assets/jquery.fancybox-1.3.4.js.gz
# pwd
/data/www/current

一切看上去挺好的啊,可是,前台一刷,就是还报“jquery.fancybox-1.3.4 isn't precompiled”,为何啊?!

别跟我说,放到直接放到 public 里,也别跟我说设置 config.assets.compile = true,这些都是 workaround,我想知道我到底卡在了哪里。 另外,查了“isn't precompile”提示只出现在 rails_helper.rb 的 digest_for 方法中,看了看,大致是说我没有设置 compile_assets 属性之类的%……&×(,不知所云了。。。

def digest_for(logical_path)
  。。。。
  if compile_assets
    if digest_assets && asset = asset_environment[logical_path]
      return asset.digest_path
    end
    return logical_path
  else
    raise AssetNotPrecompiledError.new("#{logical_path} isn't precompiled")
  end
end

前几天由于一个插件和 application.js 一起打包编译就报错 所以我单独摘了出来 layout/application.html.erb

<%= javascript_include_tag "/xheditor/xheditor-1.1.12-zh-cn" %>

在这个目录可以找到public/xheditor/

#1 楼 @shawnyu , 谢谢,不过你说的这种方式还是把 js 放到 public 目录下,我想做的是,放到 app\assets 目录下,然后 rake precompile。

像你帖子中的方法操作完毕后,这样写

<%= javascript_include_tag "/assets/jquery.fancybox-1.3.4" %>

试试

#3 楼 @shawnyu 尝试了, <%= javascript_include_tag "/assets/jquery.fancybox-1.3.4" %><%= javascript_include_tag "/assets/jquery.fancybox-1.3.4.js" %> 都试了,都不行诶~,苦闷

assets precompile 默认是只 compile application.js,如果你要 compile 其他的话,需要在 production 的配置中加上 config.assets.compile += [ XXX.js ]。 详细的可以参考 rubyonrails 的 guides 的 assets pipeline

试试这样子,单独写个 layout 出来,在里面 include 一个 js,js 里面再 require 你要的 js,然后编译 include 的那个 js

我也一直困惑于这个问题,只能用 config.assets.compile = true 暂时解决了

另外,fancybox 属于第三方组件,应该放到 vendor/assets 中,而不是 app/assets

#5 楼 @cantin 谢谢!把 JS 加入到 asset.compile 的办法我试验了,无果。

1. 在production.rb中加入预编译文件列表
#加入我们自己额外用哦js的预编译
config.assets.precompile += %w( jquery.fancybox-1.3.4.js )

嗯,你说的对,我应该做个简单的,把这个问题隔离出来试试。谢谢。

#7 楼 @HungYuHei 对,应该放到 vender 中,谢谢。

终于解决了,比较坑爹!

原因是要写成 <%= javascript_include_tag "jquery.fancybox-1.3.4.js" %> 原来的是 <%= javascript_include_tag "jquery.fancybox-1.3.4" %> 找不同喽

看到了吧,必须加上.js,为什么呢?不知道。。。 是在 stackoverflow 上寻到线索,然后自己也多次反复试验,在生产环境下,试验这东西确实是个恼人的活,编译 js,重启,等待。。。忒熬人。

http://stackoverflow.com/questions/7640808/assets-say-not-precompiled-when-they-are-precompiled

Add the .js to javascript_include_tag 'jquery.autocomplete.js'

Seems like there is an missing functionality. When the filename has a period '.' in the name, the .js extension will not get added when looking into the digest.

I did some debugging to Sprockets::Helpers::RailsHelper and it seems like digest_for methods gets the logical path without the .js.

总结一下,js 的 assets 部署步骤: 1.放置好 js 到 assets 目录,或者 vender 下(@HungYuHei 建议的对!) 2.在 production.rb 中加入编译它: config.assets.precompile += %w( jquery.fancybox-1.3.4.js ) 3.在代码中加入 include-tag <%= javascript_include_tag "jquery.fancybox-1.3.4.js" %> 如果文件名中不包含“.”,就不用加坑爹的".js"后缀了。 4.rake assets:precompile 或者 cap deploy

应该就不会有大碍了,完毕!

我的 js 文件名中不包含“.”,但是也靠加".js"後缀解决了

@piginzoo @HungYuHei 请教一下大家,如果是第三方的 js 插件,比如富文本编辑器,怎么把里面的 css 和 图片 拿出来 放到 stylesheets 和 images 目录呢,我现在是手动改 js 和 css 里引用的路径,很麻烦,不知道大家都是怎么做的?

@fresh_fish image,javasript,stylesheet 三个目录各放一份,不要改路径,必要的话把不属于各个目录的东西删了,比如 image 只保留图片的,偷懒的话就不用管了,这样的话路径引用仍是正确的

@fresh_fish 我后来处理这类似的东西,都不纠结这事了,直接放到 public/js 目录里了,不玩 assets 了,呵呵

#14 楼 @piginzoo 不是办法的办法啊

guides 里面有说,jquery-rails 就是一个很好的例子,应该可以研究一下

我遇到的问题更猛,我用了一个 jquery.fileupload-ui 的 gem,里面有个 css。但是预编译的时候压根编译不过。我又没办法修改 gem 里面的 css 内容。

nice/解决了我的问题哈哈😂 😀 😍

需要 登录 后方可回复, 如果你还没有账号请 注册新账号