簡體   English   中英

Rails 5:在生產中加載 lib 文件

[英]Rails 5: Load lib files in production

我已將我的一個應用程序從 Rails 4.2.6 升級到 Rails 5.0.0。 升級指南說,默認情況下,自動加載功能現在在生產中是禁用的。

現在我總是在我的生產服務器上收到錯誤,因為我在application.rb文件中加載了自動加載的所有 lib 文件。

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

現在,我已將config.enable_dependency_loading設置為true但我想知道是否有更好的解決方案。 默認情況下在生產中禁用自動加載肯定是有原因的。

移至 Rails 5 后我的更改列表:

  1. lib目錄放入app因為app所有代碼在 dev 中自動加載並在 prod 中預先加載,最重要的是在開發中自動重新加載,因此每次進行更改時都不必重新啟動服務器。
  2. 刪除任何指向lib您自己的類的require語句,因為如果它們的文件/目錄命名正確,它們都會自動加載,並且如果您保留require語句,它可能會中斷自動重新加載。 更多信息在這里
  3. 在所有環境中設置config.eager_load = true以在 dev 中急切地查看代碼加載問題。
  4. 使用Rails.application.eager_load! 在使用線程之前避免“循環依賴”錯誤。
  5. 如果您有任何 ruby​​/rails 擴展,則將該代碼保留在舊的lib目錄中,並從初始化程序手動加載它們。 這將確保在可以依賴它的進一步邏輯之前加載擴展:

     # config/initializers/extensions.rb Dir["#{Rails.root}/lib/ruby_ext/*.rb"].each { |file| require file } Dir["#{Rails.root}/lib/rails_ext/*.rb"].each { |file| require file }

我只是使用config.eager_load_paths而不是config.autoload_paths就像在 github 評論中提到 akostadinov 一樣: https : //github.com/rails/rails/issues/13142#issuecomment-275492070

# config/application.rb
...
# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')

它適用於開發和生產環境。

感謝Johan建議用Rails.root.join('lib')替換#{Rails.root}/lib

由於線程安全,自動加載在生產環境中被禁用。 感謝@Зелёный 提供鏈接。

我按照Github 上的建議將 lib 文件存儲在我的app目錄中的lib文件夾中,從而解決了這個問題。 Rails 會自動加載app文件夾中的每個文件夾。

默認情況下在生產中禁用自動加載肯定是有原因的。

這是關於這個問題的長時間討論。 https://github.com/rails/rails/issues/13142

這允許 lib autoreload,並且也可以在生產環境中使用。

PS我已經改變了我的答案,現在它增加了兩個急切的自動加載路徑,無論環境如何,也允許在自定義環境中工作(如舞台)

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...

只需將 config/application.rb 文件中的config.autoload_paths更改為config.eager_load_paths 即可 因為在 rails 5 中,生產環境默認禁用自動加載。 欲了解更多詳情,請點擊鏈接

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

它適用於環境開發和生產。

從某種意義上說,這是 Rails 5 中統一的方法來集中 Eager 和 Autoload 配置,同時它會在配置 Eager 加載時添加所需的自動加載路徑,否則將無法正常工作:

# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true

# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...

對於像我一樣為此苦苦掙扎的人,僅在app/下放置一個目錄是不夠的。 是的,您將獲得自動加載,但不需要重新加載,這需要滿足命名空間約定

此外,使用初始化程序加載舊的根級lib將防止在開發過程中重新加載功能。

將 lib 文件夾移動到 app 有助於解決一個問題,我的 Twitter api 無法在生產環境中運行。 我有“未初始化的常量 TwitterApi”,我的 Twitter API 在我的 lib 文件夾中。 我的config.autoload_paths += Dir["#{Rails.root}/app/lib"]config.autoload_paths += Dir["#{Rails.root}/app/lib"]但在移動文件夾之前它不起作用。

這成功了

我同意某些依賴項屬於lib ,有些可能屬於app/lib

我更喜歡為所有環境加載我選擇放在lib所有文件,因此我在需要包之后但在打開MyApplicationName模塊之前立即在config/application.rb執行此操作。

# load all ruby files in lib
Dir[File.expand_path('../../lib/**/*.rb', __FILE__)].each { |file| require file }

這不依賴於Rails.root (尚未定義),也不依賴於預先加載(對於環境可能已關閉)。

唯一對我有用的是在急切加載路徑中添加嵌套的 lib 路徑並在 config.to_prepare 塊中添加 require_dependency 。

# application.rb
...
config.to_prepare do
  require_dependency("#{Rails.root}/lib/spree/core/product_filters.rb")
end

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

總結 Lev 的回答: mv lib app足以讓我所有的lib代碼自動加載/自動重新加載。

(rails 6.0.0beta3 但在 rails 5.x 上也應該可以正常工作)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM