@ledsun blog

無味の味は佳境に入らざればすなわち知れず

jsbundling-rails

github.com

esbuild-rails - @ledsun blogで紹介したesbuild-railsの後継Gemです。

最初は次の2つのGemのようにバンドラー毎に、別々のGemとして作られていました。

三つ統合しても、あるいは他のバンドラーを増やしても、それほど複雑にならないと判断したのか、一つのGemになりました。

実装内容もesbuild-railsとほとんど変わりません。 railsコマンドで実行するRakeタスクがあり、そこからapp:templateタスクを起動してファイルを追加します。

javascript:[esbuild|rollup|webpack]:installタスク

https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/tasks/jsbundling/install.rake

    desc "Install shared elements for all bundlers"
    task :shared do
      system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../../install/install.rb",  __dir__)}"
    end

    desc "Install esbuild"
    task esbuild: "javascript:install:shared" do
      system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../../install/esbuild/install.rb",  __dir__)}"
    end

    desc "Install rollup.js"
    task rollup: "javascript:install:shared" do
      system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../../install/rollup/install.rb",  __dir__)}"
    end

    desc "Install Webpack"
    task webpack: "javascript:install:shared" do
      system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../../install/webpack/install.rb",  __dir__)}"
    end

共通のinstall/install.rbとバンドラーごとのinstall/esbuild/install.rbを実行します。

install/install.rb

https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/install.rb

say "Compile into app/assets/builds"
empty_directory "app/assets/builds"
keep_file "app/assets/builds"
append_to_file "app/assets/config/manifest.js", %(//= link_tree ../builds .js\n)

if Rails.root.join(".gitignore").exist?
  append_to_file ".gitignore", %(/app/assets/builds\n)
end

if (app_layout_path = Rails.root.join("app/views/layouts/application.html.erb")).exist?
  say "Add JavaScript include tag in application layout"
  insert_into_file app_layout_path.to_s,
    %(\n    <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>), before: /\s*<\/head>/
else
  say "Default application.html.erb is missing!", :red
  say %(        Add <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %> within the <head> tag in your custom layout.)
end

unless (app_js_entrypoint_path = Rails.root.join("app/javascript/application.js")).exist?
  say "Create default entrypoint in app/javascript/application.js"
  empty_directory app_js_entrypoint_path.parent.to_s
  copy_file "#{__dir__}/application.js", app_js_entrypoint_path
end
  1. app/assets/buildsディレクトリを作る
  2. app/assets/config/manifest.jsに↑のディレクトリを追加
  3. .gitignoreに↑のディレクトリを追加
  4. app/views/layouts/application.html.erb<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>を追加
  5. app/javascript/application.jshttps://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/application.js (実質空ファイル)をコピーします。

esbuild/install.rb

https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/esbuild/install.rb

say "Create default package.json and install esbuild"
copy_file "#{__dir__}/package.json", "package.json"
run "yarn add esbuild"
  1. https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/esbuild/package.json をコピー
  2. yarn add esbuildを実行

rollup/install.rb

https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/rollup/install.rb

say "Create default package.json and install rollup with config"
copy_file "#{__dir__}/package.json", "package.json"
copy_file "#{__dir__}/rollup.config.js", "rollup.config.js"
run "yarn add rollup @rollup/plugin-node-resolve"
  1. https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/rollup/package.json をコピー
  2. https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/rollup/rollup.config.js をコピー
  3. yarn add rollup @rollup/plugin-node-resolve を実行

esbuildと異なり、デフォルトで設定ファイルもコピーします。

https://github.com/rails/jsbundling-rails/issues/8#issuecomment-914315207

I think the part that feels different to me is that esbuild's config is more like an actual program that uses esbuild as an API. Perhaps that's a subtle difference, but it feels distinct to me. When you literally have to parse your own ARGV, then it's clearly a different territory to rollup.config.js or webpack.config.js.

DHHはesbuildの設定ファイルがいかにもスクリプトな点が気になっているため、esbuildでは設定ファイルを入れていないようです。

webpack/install.rb

https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/webpack/install.rb

say "Create default package.json and install Webpack with config"
copy_file "#{__dir__}/package.json", "package.json"
copy_file "#{__dir__}/webpack.config.js", "webpack.config.js"
run "yarn add webpack webpack-cli"
  1. https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/webpack/package.json をコピー
  2. https://github.com/rails/jsbundling-rails/blob/v0.1.1/lib/install/webpack/webpack.config.js をコピー
  3. yarn add webpack webpack-cli を実行

webpackはrollupとほとんど変わりがありません。 yarnコマンドでインストールするパッケージが違う程度です。

Webpackerのときと異なりwebpackの設定ファイルがそのまま使われるようです。

感想

本当にDSLなんですね