Ruby & RailsRuby on RailsRuby

Rails 5 生产环境默认关闭 autoloading

2016-09-12  本文已影响742人  老码农不上班

开发 payslip 时,有一个自定义模块放在 lib/payslip目录下,在 config/application.rb目录下添加了config.autoload_paths << Rails.root.join('lib'),开发环境中跑的好好的,但部署之后,却遇到模块没加载的错误。然后就翻了一下相关文档以及博客。
默认你已经了解自动加载,如果不熟悉的话,请在 Rails 指南中查阅对应文档 Autoloading and Reloading Constants

Eagerload paths

Autoloading 是线程不安全,所以我们要确保 Rails 应用跑起来时所有的常量(Autoloading and Reloading Constants)都加载进来。在使用之前加载所有常量的概念就是 Eagerload ,反之就是 Autoloading, Autoloading就是需要使用时才把常量加载。譬如当一个 class 被需要且没有在内存中找到时,Rails 就会在 autoloading paths路径中查找并加载。
eager_load_paths包含一些列目录,当 Rails 应用在在生产环境中启动,同时会把列在eager_load_paths中所列的文件或者文件目录加载。
例如:

# config/application.rb

config.eager_load_paths << Rails.root.join('lib')

Rails 5 生产环境默认不允许 autoloading

就像今天我遇到的错误一下,虽在 config.autoload_paths中把lib文件目录添加了,但是在生产环境中仍然找不到需要用的模块。原因就在于此。
通过这个 commit可得知,Rails 应用在生产环境不会执行 autoloading
在生产环境中,Rails 会从 eager_load_paths中加载所有常量(文件),如果找不到常量,再也不会通过 autoload_paths继续寻找。
这是比较大的一个改动,如果之前的项目使用了 autoload_paths,升级到 Rails 5 时需要作出对应的改动。譬如之前在 config/application.rb中如果 config.autoload_paths << Rails.root.join('lib'),则你需要改为 config.eager_load_paths << Rails.root.join('lib')
另外,在极少数情况下,如果Rails 5 项目很有必要继续沿用 autoloading,可通过把 enable_dependency_loading 设置为 true。但是不推荐,我试过通过这样的方式,发现在生产环境中,访问页面,整个性能都慢下来了。

# config/application.rb

config.enable_dependency_loading = true
config.autoload_paths << Rails.root.join('lib')

推荐阅读:
confusing about autoload_paths vs eager_load_paths in rails 4谈到了 autoload-paths 导致页面访问慢的问题。
In production, custom autoload_paths are not respected

上一篇下一篇

猜你喜欢

热点阅读