Rails 앱을 위한 더 빠른 RuboCop 실행

최근 Nate Berkopec은 흥미로운 관찰 결과를 공유했습니다. 실행bundle exec whatever은 Gemfile이 크면(실행 파일 자체에 약간의 종속성이 필요한 경우에도) 부팅하는 데 몇 초가 걸릴 수 있습니다.






네이트 버코펙


@nateberkopec






잠금에 총 500개의 종속성과 같은 거대한 Gemfile이 있다고 가정해 보겠습니다. 이 Gemfile에 ~5개의 보석이 있는 그룹이 있습니다. Bundler.setup(:nameofgroup) 이 5개의 gem만 있는 별도의 Gemfile을 유지하는 것보다 훨씬 느린 이유는 무엇입니까?


오후 14:48 - 2022년 2월 18일









이는 Bundler가 Gemfile.lock 파일 일관성을 확인해야 한다는 사실로 설명할 수 있습니다(모든 gem이 설치됨). 따라서 이는 예상되는 동작입니다(개선하려고 시도해서는 안 된다는 의미는 아닙니다. 예를 들어 Matthew Draper의 Gel 참조).

Rails 개발자는 일반적으로 RuboCop 과 같은 개발 도구를 포함하여 모든 deps를 Gemfile 에 넣습니다. RuboCop은 린터이며 린터는 빨라야 합니다. RuboCop 자체는 이 설명을 준수하지만 Bundler를 통해 실행하면 그렇지 않을 수 있습니다.

이것을 어떻게 극복할 수 있습니까? 별도의 Gemfile 사용!

저는 CI RuboCop 실행 속도를 높이기 위해(linter 종속성만 설치하여) 보석 개발에 오랫동안 이 기술을 사용해 왔습니다. 여기 내 typical rubocop.gemfile 이 있습니다.

# gemfiles/rubocop.gemfile
source "https://rubygems.org" do
  gem "rubocop-md", "~> 1.0"
  gem "rubocop-rspec"
  gem "standard", "~> 1.0"
end


Bundler와 함께 사용하려면 BUNDLER_GEMFILE env 변수를 지정해야 합니다.

# first, install the deps
BUNDLE_GEMFILE=gemfiles/rubocop.gemfile bundle install

# then, run the executable
BUNDLE_GEMFILE=gemfiles/rubocop.gemfile bundle exec rubocop


이 장황한 접근 방식은 기계(CI)에는 충분히 잘 작동하지만 사람에게는 적합하지 않습니다. 별도의 잠금 파일을 유지 관리하고 개발 시 환경 변수를 사용하는 것은 완벽한 사용자 경험과는 거리가 멉니다.

Rails 애플리케이션 개발을 위해 사용자 지정 gemfile로 지원되는 명령을 실행하기 위해 간단한 bin/whatever 래퍼를 추가하는 다음 트릭을 생각해 냈습니다. 다음은 우리의 bin/rubocop입니다.

#!/bin/bash

cd $(dirname $0)/..

export BUNDLE_GEMFILE=./gemfiles/rubocop.gemfile
bundle check > /dev/null || bundle install

bundle exec rubocop $@


마법의 $@ 인수는 bin/rubocop에 전달하는 모든 것을 프록시하므로 이 래퍼를 RuboCop처럼 꽥꽥거리게 만듭니다.

또한 bundle check || bundle install를 수행하여 모든 deps가 있는지 확인합니다(따라서 bundle install를 직접 실행할 필요가 없습니다).

그게 다야.

추신 왜 인라인 gemfiles( as )를 사용하지 않습니까? 다음과 같이 bin/rubocop를 작성할 수 있습니다.

require 'bundler/inline'

gemfile(true, quiet: true) do
  gem "rubocop-md", "~> 1.0"
  gem "rubocop-rspec"
  gem "standard", "~> 1.0"
end

require 'rubocop'
RuboCop::CLI.new.run


그러나 이 접근 방식을 사용하면 잠금 파일이 전혀 없습니다. 모든 사람이 동일한 버전의 종속성을 사용하고 있는지 확인하고 싶습니다("내 컴퓨터에서 작동"하는 상황을 방지하기 위해). 물론 gemfile do ... end 블록에서 정확한 버전을 사용할 수 있지만 IMO, Bundler로 deps를 관리하는 것이 더 편리합니다(예: bundle update 를 실행할 수 있음).

추신 이 접근 방식의 이점 중 하나는 Kuby 을 사용하는 동안 린터(및 Docker for application development 와 같은 기타 도구)를 로컬에서 실행할 수 있다는 것입니다. RuboCop을 실행하기 위해 컨테이너를 가동할 필요가 없습니다. Git 후크 또는 편집기 통합을 사용하려는 경우 특히 유용합니다.

좋은 웹페이지 즐겨찾기