Rails는 app/javascript를 어떻게 처리할까?
Rails에서는 Asset Pipeline이라는 기능을 통해 정적 애셋 파일을 처리한다. Rails Asset Pipeline(Propshaft)은 기본적으로 app/assets
디렉토리 하위 디렉토리(e.g. app/assets/images
, app/assets/javascripts
, app/assets/stylesheets
)의 파일을 public/assets
로 옮겨주는 기능을 제공한다.
Rails에서 js 파일을 사용하기 위해서는 가장 단순하게는 app/assest/javascripts
에 js 파일을 작성하는 방법이 있다. 하지만 이 방법을 사용하는 경우 필요한 js 파일을 직접 로드해줘야 하고, 외부 의존성을 사용하는 경우에는 관리하기 어려워지는 단점이 있다. 이러한 문제를 해결하기 위해 Rails에서는 js 파일을 사용하는 두 가지 방법을 제안하는데 첫 번째는 importmap
이고 다른 하나는 jsbundling-rails
를 사용하는 방법이다.
이 두 가지 방법을 사용해 Rails 프로젝트를 세팅해보면 javascript 파일을 app/assets/javascripts
디렉토리가 아닌 app/javascript
디렉토리 하위에 작성하게 되는 것을 알 수 있다. 위에서 설명했듯이 Asset pipeline은 app/assets
디렉토리 하위 디렉토리의 파일만 처리한다고 했는데, 그렇다면 importmap 또는 jsbundling-rails을 사용하는 경우 어떻게 app/javascript
의 파일을 처리하는 걸까?
Asset Pipeline에서는 Rails.application.config.assets.paths
을 통해 app/assets
이외의 원하는 경로를 Asset Pipeline의 경로로 추가할 수 있도록 하고 있다. importmap에서는 바로 이 방법을 사용하는데, importmap의 소스 코드를 보면 알 수 있다. 코드를 보면 Rails 초기화 과정에서 app.config.assets.paths
에 app/javascript
와 vendor/javascript
디렉토리를 추가하고 있다. 이로 인해 importmap을 사용하는 경우 app/javascript
디렉토리 하위의 파일도 Asset Pipeline에 의해 처리될 수 있게 된다.
initializer "importmap.assets" do |app|
if app.config.respond_to?(:assets)
app.config.assets.paths << Rails.root.join("app/javascript")
app.config.assets.paths << Rails.root.join("vendor/javascript")
end
end
반면 jsbundling-rails
는 다른 접근을 사용한다. jsbundling-rails는 importmap처럼 app/javascript
디렉토리를 처리하는 기능을 직접 제공하지 않으며, 사용자가 직접 번들링 output의 위치를 app/assets/builds
로 설정하도록 안내한다. 예를 들어 bin/rails javascript:install:esbuild
로 esbuild를 설정해보면 build 스크립트가 아래와 같이 설정되어 번들링 후 결과물이 app/assets/builds
에 들어가는 것을 볼 수 있다. 해당 위치는 app/assets
하위에 존재하므로 자연스럽게 Asset Pipeline에 의해 처리된다.
{
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets"
}
}