Elixirのesbuildラッパーは何をしているのか
この記事はfukuoka.ex Elixir/Phoenix アドベントカレンダー Advent Calendar 2021の9日目です🎄
8日目は@Gsannさんの【Elixir】ElixirとOOP、プログラミングスタイルの違い でした。
今日のテーマ
アドベントカレンダー1日目にPhoenix v1.6の変更点をまとめました。
この記事の中で紹介している アセット管理の章 冒頭で次のように記述しています。
Phoenix v1.6からは、新しいアプリケーションはesbuildを使い、Elixirのesbuildラッパーを介してアセットを準備します。このように esbuild と直接統合されたことで、新しく生成されたアプリケーションは、Node.jsや外部のビルドシステム(Webpackなど)に依存することがなくなりました。
Phoenix v1.6ではwebpackに代わり、esbuildを利用したJavaScriptのバンドルが標準仕様となりました。
そこでこの記事では、esbuildとはなんぞや、またそのラッパーとはなんぞやというのをまとめてみたいと思います。
esbuildとは
esbuildはGolang製のJavaScriptのbundlerです。extremely fast
と謳ってあることから、パフォーマンスがウリなようです。
An extremely fast JavaScript bundler
three.jsというJavaScriptの3Dツールを10回復製したもの(?)をバンドルするのにかかった時間がグラフで表示されており、爆速具合がアピールされています...!
なぜそんなにも速いの?という質問はFAQにまとまっています。
- Goで記述されており、ネイティブコードにコンパイルされる
- 並列処理を行なっている
- 0からパフォーマンスを意識して作った
などなど、高速な理由が挙げられています。
そんなesbuildですが、Phoenix v1.6からはwebpackの代わりとして標準搭載されました。FAQの「Used by other projects」の部分にもPhoenixが事例として挙げられています!なんだか嬉しい!
Used by other projects
The API is already being used as a library within many other developer tools. For example, Vite and Snowpack are using esbuild to transform TypeScript into > JavaScript and Amazon CDK (Cloud Development Kit) and Phoenix are using esbuild to bundle code.
このesbuildがPhoenixでどのように利用されるのか、深堀りしてみましょう。
Elixirのesbuildラッパー
Phoenix Frameworkのorganizationでesbuildという同じ名前でライブラリが実装されています。
先に紹介したGolang製のesbuildをElixirプロジェクトでも楽に導入できるように、インストール〜実行までを支援してくれます。
Esbuild.install/0を見るのが1番分かりやすいのですが、
- 実行したos、architectureの情報を取得(これでDLすべき実行ファイルを特定)
- npmで公開されている実行ファイルをダウンロード、
-
_build
に保存(デフォルトの挙動)
という流れで実行されるようです。
本家esbuildにもドキュメントに記載がある方法ですね。
あとは _build
にDLした実行ファイルをOptionをよしなにつけて System.cmd/3
で実行します(コード参考)
こう見ると「実行ファイルをDLして _build
に置いて実行する」という意外とシンプルな実装です。これがEsbuildライブラリが担っている役割です。
Phoenixと組み合わせる
Phoenix.Endpoint
には :watcher
というオプションがあり、Phoenixサーバーの起動と合わせて、Elixir関数の実行や、任意のコマンドを実行できます。
:watchers - a set of watchers to run alongside your server. It expects a list of tuples containing the executable and its arguments. Watchers are guaranteed to run in the application directory, but only when the server is enabled. For example, the watcher below will run the "watch" mode of the webpack build tool when the server starts. You can configure it to whatever build tool or command you want:
phoenix v1.6ではこのwatcherの仕組みを活用して、dev.exs
にesbuildのダウンロードと実行の設定があらかじめ組み込まれています。
watchers: [
# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
]
- Esbuildライブラリの
install_and_run/2
を実行してサーバー起動時にesbuildのDLと実行まで行う - esbuildは
--watch
オプション付きで実行
という流れです。Phoenixが行なっているのはサーバー起動時にElixirの Esbuild
ライブラリを介して esbuild
を実行するまでで、変更の監視自体はesbuild側で行なっているというところがポイントです。
この仕組みにより、ユーザーがあまり意識せずとも「開発環境でPhoenixサーバーを起動するだけでassets/
配下のビルドと監視が走るぞ...!」となるわけです。
dev環境でサーバーを起動後、実際に _build
ディレクトリの中を見てみるとesbuildの存在が確認できると思います。
$ ls -1 _build
dev
esbuild-darwin-64
また、本番環境にdeployする際に実行する mix assets.deploy
もオプションの違いはありながらも、結局はEsbuildライブラリを介して esbuild
を実行しています。
defp aliases do
[
...
"assets.deploy": ["esbuild default --minify", "phx.digest"]
]
end
まとめ
Phoenix v1.6で標準搭載されたesbuildについて紹介しました。「結局は _build
に落としてきた実行ファイルを実行している」というのが分かれば色々と読み解きやすいと思います。
明日は@tuchiroさんの記事です。お楽しみに!
Discussion