You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5.2.8.1升级至6.1时CircleCI资产预编译Zeitwerk冲突问题

Rails 6.1升级资产预编译时Zeitwerk加载器冲突问题

我们有一个Rails 5.2.8.1应用,正在升级到Rails 6.1。本地运行仅出现少量问题,但在CircleCI执行资产预编译时触发错误:Zeitwerk的rails.once加载器试图管理actiontext-6.1.7/app/helpers目录,而该目录已被默认的rails.main加载器接管。我们并未手动使用过这个load once加载器。

application.rb中的加载器配置

config.autoload_paths += %W[
  #{config.root}/lib
  #{config.root}/lib/simple_form
  #{config.root}/app/jobs
  #{config.root}/app/jobs/concerns
  #{config.root}/app/controllers/concerns
  #{config.root}/app/mailers/concerns
  #{config.root}/app/models/concerns
  #{config.root}/app/models/reports
  #{config.root}/app/services/pdf_data
  #{config.root}/app/presenters
  #{config.root}/app/assets/templates
  #{config.root}/app/event_handlers
  #{config.root}/app/queries
  #{config.root}/app/concepts
  #{config.root}/vendor/
  #{config.root}/app/pdfs
]

config.eager_load_paths += %W[
  #{config.root}/lib
]

错误输出

#!/bin/bash -eo pipefail
WEBPACKER_PRECOMPILE=false RAILS_NO_DB=true bundle exec rake assets:precompile --trace
** Invoke assets:precompile (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
** Invoke environment (first_time)
** Execute environment
rake aborted!
Zeitwerk::Error: loader

#<Zeitwerk::Loader:0x000055eb81710b98
 @autoloaded_dirs=[],
 @autoloads={},
 @collapse_dirs=#<Set: {}>,
 @collapse_glob_patterns=#<Set: {}>,
 @eager_load_exclusions=#<Set: {}>,
 @eager_loaded=false,
 @ignored_glob_patterns=#<Set: {}>,
 @ignored_paths=#<Set: {}>,
 @inflector=ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector,
 @initialized_at=2022-12-07 14:27:29.123263169 +0000,
 @logger=nil,
 @mutex=#<Thread::Mutex:0x000055eb81710738>,
 @mutex2=#<Thread::Mutex:0x000055eb81710710>,
 @namespace_dirs={},
 @on_load_callbacks={},
 @on_setup_callbacks=[],
 @on_unload_callbacks={},
 @reloading_enabled=false,
 @roots={},
 @setup=false,
 @shadowed_files=#<Set: {}>,
 @tag="rails.once",
 @to_unload={}>


wants to manage directory /home/circleci/flightlogger-rails/vendor/bundle/ruby/2.7.0/gems/actiontext-6.1.7/app/helpers, which is already managed by

#<Zeitwerk::Loader:0x000055eb81712f88
 @autoloaded_dirs=[],
 @autoloads={},
 @collapse_dirs=#<Set: {}>,
 @collapse_glob_patterns=#<Set: {}>,
 @eager_load_exclusions=
  #<Set: {"/home/circleci/flightlogger-rails/lib/simple_form",
   "/home/circleci/flightlogger-rails/app/models/reports",
   "/home/circleci/flightlogger-rails/app/assets/templates",
   "/home/circleci/flightlogger-rails/vendor"}>,
 @eager_loaded=false,
 @ignored_glob_patterns=#<Set: {}>,
 @ignored_paths=#<Set: {}>,
 @inflector=ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector,
 @initialized_at=2022-12-07 14:27:29.122727016 +0000,
 @logger=nil,
 @mutex=#<Thread::Mutex:0x000055eb81712ab0>,
 @mutex2=#<Thread::Mutex:0x000055eb81712a88>,
 @namespace_dirs={},
 @on_load_callbacks={},
 @on_setup_callbacks=[],
 @on_unload_callbacks={},
 @reloading_enabled=false,
 @roots=
  {"/home/circleci/flightlogger-rails/lib"=>Object,
   "/home/circleci/flightlogger-rails/lib/simple_form"=>Object,
   "/home/circleci/flightlogger-rails/app/jobs"=>Object,
   "/home/circleci/flightlogger-rails/app/jobs/concerns"=>Object,
   "/home/circleci/flightlogger-rails/app/controllers/concerns"=>Object,
   "/home/circleci/flightlogger-rails/app/mailers/concerns"=>Object,
   "/home/circleci/flightlogger-rails/app/models/concerns"=>Object,
   "/home/circleci/flightlogger-rails/app/models/reports"=>Object,
   "/home/circleci/flightlogger-rails/app/presenters"=>Object,
   "/home/circleci/flightlogger-rails/app/assets/templates"=>Object,
   "/home/circleci/flightlogger-rails/app/event_handlers"=>Object,
   "/home/circleci/flightlogger-rails/app/queries"=>Object,
   "/home/circleci/flightlogger-rails/app/concepts"=>Object,
   "/home/circleci/flightlogger-rails/vendor"=>Object,
   "/home/circleci/flightlogger-rails/app/pdfs"=>Object,
   "/home/circleci/flightlogger-rails/app/associations"=>Object,
   "/home/circleci/flightlogger-rails/app/channels"=>Object,
   "/home/circleci/flightlogger-rails/app/controllers"=>Object,
   "/home/circleci/flightlogger-rails/app/decorators"=>Object,
   "/home/circleci/flightlogger-rails/app/forms"=>Object,
   "/home/circleci/flightlogger-rails/app/graphql"=>Object,
   "/home/circleci/flightlogger-rails/app/graphql/concerns"=>Object,
   "/home/circleci/flightlogger-rails/app/helpers"=>Object,
   "/home/circleci/flightlogger-rails/app/interactors"=>Object,
   "/home/circleci/flightlogger-rails/app/mailers"=>Object,
   "/home/circleci/flightlogger-rails/app/models"=>Object,
   "/home/circleci/flightlogger-rails/app/permitters"=>Object,
   "/home/circleci/flightlogger-rails/app/policies"=>Object,
   "/home/circleci/flightlogger-rails/app/public_api"=>Object,
   "/home/circleci/flightlogger-rails/app/serializers"=>Object,
   "/home/circleci/flightlogger-rails/app/services"=>Object,
   "/home/circleci/flightlogger-rails/app/validators"=>Object,
   "/home/circleci/flightlogger-rails/vendor/bundle/ruby/2.7.0/gems/jquery-minicolors-rails-2.2.6.2/app/inputs"=>
    Object,
   "/home/circleci/flightlogger-rails/engines/sms/app/concerns"=>Object,
   "/home/circleci/flightlogger-rails/engines/sms/app/controllers"=>Object,
   "/home/circleci/flightlogger-rails/engines/sms/app/helpers"=>Object,
   "/home/circleci/flightlogger-rails/engines/sms/app/inputs"=>Object,
   "/home/circleci/flightlogger-rails/engines/sms/app/mailers"=>Object,
   "/home/circleci/flightlogger-rails/engines/sms/app/models"=>Object,
   "/home/circleci/flightlogger-rails/vendor/bundle/ruby/2.7.0/gems/sentry-rails-5.6.0/app/jobs"=>
    Object,
   "/home/circleci/flightlogger-rails/vendor/bundle/ruby/2.7.0/gems/react_on_rails-13.1.0/app/helpers"=>
    Object},
 @setup=false,
 @shadowed_files=#<Set: {}>,
 @tag="rails.main",
 @to_unload={}>

问题根源

你把#{config.root}/vendor/加到了config.autoload_paths里,这让Zeitwerk主加载器把整个vendor目录都管了起来,包括里面的vendor/bundle(bundler安装gem的目录)。而ActionText的app/helpers目录本来是由Rails自带的rails.once加载器负责的,两个加载器抢同一个目录,就引发了冲突。

另外,Rails 6+用Zeitwerk当默认自动加载器,像app/jobs、app/controllers/concerns这些标准目录,Zeitwerk会自动识别,根本不用手动加到autoload_paths里,之前的配置纯属画蛇添足。

修复方法

  1. 清理autoload_paths,删掉多余条目
    把config.autoload_paths里的标准目录和vendor/全删掉,只留自定义的目录:

    config.autoload_paths += %W[
      #{config.root}/lib
      #{config.root}/lib/simple_form
      #{config.root}/app/models/reports
      #{config.root}/app/services/pdf_data
      #{config.root}/app/presenters
      #{config.root}/app/assets/templates
      #{config.root}/app/event_handlers
      #{config.root}/app/queries
      #{config.root}/app/concepts
      #{config.root}/app/pdfs
    ]
    

    重点是必须删掉#{config.root}/vendor/,这是冲突的核心原因。

  2. 如果要加载vendor下的自定义代码,别直接加整个目录
    要是vendor里有你自己写的代码要加载,别把整个vendor目录加进去,只加具体的子目录,比如:

    # 比如vendor下有custom_code目录需要加载
    config.autoload_paths += %W[#{config.root}/vendor/custom_code]
    

    绝对不能让加载器管到vendor/bundle,那是gem的地盘。

  3. 检查eager_load_paths
    config.eager_load_paths里的#{config.root}/lib可以留着,要是lib目录的结构符合Zeitwerk的命名规则,其实不加也没事,留着也不影响。

  4. CircleCI命令可选调整
    试试给预编译命令加上RAILS_ENV=production,确保环境一致:

    WEBPACKER_PRECOMPILE=false RAILS_NO_DB=true RAILS_ENV=production bundle exec rake assets:precompile --trace
    

验证

先在本地跑一遍预编译命令,确认没问题:

WEBPACKER_PRECOMPILE=false RAILS_NO_DB=true bundle exec rake assets:precompile

本地正常的话,再推到CircleCI测试。

内容的提问来源于stack exchange,提问作者Nicholas Ladefoged

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:40:33