Rails7+Sprockets新项目在CircleCI中找不到application.js文件
问题描述
执行rails new --javascript=esbuild创建的Rails7新项目(使用ESbuild做JS打包),在CircleCI运行测试时抛出以下错误:
Sprockets::Rails::Helper::AssetNotFound in Home#index
The asset "application.js" is not present in the asset pipeline.
项目在本地开发环境及Heroku部署后均可正常运行,仅CircleCI测试环节出现该问题。
复现步骤
- 执行
rails new --javascript=esbuild初始化项目 - 安装rspec测试框架
- 配置CircleCI并将项目接入流水线
- 创建输出“Hello world”的基础控制器
- 设置该控制器为根路由
- 添加如下系统测试用例:
require 'rails_helper' describe "can load the homepage" do it "should load the homepage" do visit "/" expect(page).to have_content("Hello world") end end
已尝试的解决操作
修改app/assets/config/manifest.js文件,添加:
//= link_directory ../../javascript .js
(注:javascript文件夹默认位于app/而非app/assets下)
CircleCI配置文件
version: 2.1 # Use 2.1 to enable using orbs and other features. # Declare the orbs that we'll use in our config. # read more about orbs: https://circleci.com/docs/2.0/using-orbs/ orbs: ruby: circleci/ruby@1.0 node: circleci/node@2 browser-tools: circleci/browser-tools@1.2.3 jobs: build: # our first job, named "build" docker: - image: cimg/ruby:3.1.2-browsers # use a tailored CircleCI docker image. auth: username: mydockerhub-user password: $DOCKERHUB_PASSWORD # context / project UI env-var reference - image: redis:6.2.6 steps: - checkout # pull down our git code. - ruby/install-deps # use the ruby orb to install dependencies # use the node orb to install our packages # specifying that we use `yarn` and to cache dependencies with `yarn.lock` # learn more: https://circleci.com/docs/2.0/caching/ - node/install-packages: pkg-manager: yarn cache-key: "yarn.lock" - run: name: Build assets command: bundle exec rails assets:precompile test: # our next job, called "test" parallelism: 1 # here we set TWO docker images. docker: - image: cimg/ruby:3.1.2-browsers # this is our primary docker image, where step commands run. auth: username: mydockerhub-user password: $DOCKERHUB_PASSWORD # context / project UI env-var reference - image: redis:6.2.6 - image: circleci/postgres:9.5-alpine auth: username: mydockerhub-user password: $DOCKERHUB_PASSWORD # context / project UI env-var reference environment: # add POSTGRES environment variables. POSTGRES_USER: circleci-demo-ruby POSTGRES_DB: VDQApp_test POSTGRES_PASSWORD: "" # environment variables specific to Ruby/Rails, applied to the primary container. environment: BUNDLE_JOBS: "3" BUNDLE_RETRY: "3" PGHOST: 127.0.0.1 PGUSER: circleci-demo-ruby PGPASSWORD: "" RAILS_ENV: test # A series of steps to run, some are similar to those in "build". steps: - browser-tools/install-chrome - browser-tools/install-chromedriver - checkout - ruby/install-deps - node/install-packages: pkg-manager: yarn cache-key: "yarn.lock" # Here we make sure that the secondary container boots # up before we run operations on the database. - run: name: Wait for DB command: dockerize -wait tcp://localhost:5432 -timeout 1m - run: name: Load schema command: bin/rails db:schema:load RAILS_ENV=test # Run rspec in parallel - ruby/rspec-test # We use workflows to orchestrate the jobs that we declared above. workflows: version: 2 build_and_test: # The name of our workflow is "build_and_test" jobs: # The list of jobs we run as part of this workflow. - build # Run build first. - test: # Then run test, requires: # Test requires that build passes for it to run. - build # Finally, run the build job.
解决方法
1. 解决CircleCI Job间资产不共享问题
CircleCI的Build和Test是独立运行的Job,默认不会共享文件系统。你在Build Job中执行的assets:precompile产物,Test Job无法直接访问,有两种处理方式:
方式一:在Test Job中重新编译资产
修改Test Job的步骤,在node/install-packages之后添加测试环境的资产编译命令:
- run: name: Build assets for test command: bundle exec rails assets:precompile RAILS_ENV=test
方式二:通过Workspace共享编译产物
在Build Job的最后添加保存Workspace的步骤:
- persist_to_workspace: root: . paths: - public/assets - tmp/cache/assets
然后在Test Job的checkout步骤之后添加恢复Workspace的操作:
- attach_workspace: at: .
2. 确认Test环境的资产配置
检查config/environments/test.rb,确保启用了必要的资产服务设置:
config.assets.compile = true config.public_file_server.enabled = true
3. 清理冗余的Sprockets配置
由于项目使用ESbuild管理JS资产,无需通过Sprockets引入javascript目录下的文件。可以移除app/assets/config/manifest.js中添加的//= link_directory ../../javascript .js配置,确保视图中使用Rails7默认的ESbuild资产标签:
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
内容的提问来源于stack exchange,提问作者Jason FB

