zenn, しずかなインターネットを作ったあのcatnoseさんがこんなツイートをしていた.
vite, React, Hono, Remix.Reactは使い倒しているのでともかく,vite, Hono, Remixの話は最近(もはや最近でもないけど)よく聞く.今日はviteについてちょっと調べてみることにした.見たリンクはこんな感じ.
これらを読んでなんとなくわかったことはこんな感じ
従来の単純なhtmlからjavascriptを呼び出すという構造ではなくなり,バンドラと呼ばれるブラウザで実行可能なようにソースモジュールをクロール,処理,連結するツールが必要になった
なお,バンドラ及びwebpackについてはhttps://zenn.dev/sprout2000/articles/9d026d3d9e0e8f参照
こうして生まれたのがwebpack(とかその他バンドラ)
しかし,大規模なアプリケーションが作られるようになり,取り扱うjavascriptの量が劇的に増え,javascriptベースのツールでは遅くなってしまった
ってことはviteはjavascriptベースのツールではない?
実際そうらしくviteはesbuildを使って依存関係の事前バンドルをするらしい
ほんでesbuildがgoベースなので10~100倍の速度が出るとか
何はともあれviteは速いらしい.速い主な要因は
サーバーの起動
esbuildによる依存関係の事前バンドル
あるライブラリAに内部モジュールが100個存在するとそのライブラリをimportするときにブラウザは100以上のリクエストを処理することになる.こうするとネットワークが混雑してしまいページ読み込みが遅くなるよね.事前にライブラリAを単一のモジュールにバンドルすることでリクエストを飛ばす回数が1回になるのでその分早くなるよ!しかもesbuildはgoベースのツールなのでjavascriptベースより断然速いよ!
ネイティブESMを行使してソースコードを提供する
viteはブラウザのリクエストに応じてソースコードを変換して提供s流のみになり,良いことがあるらしい...
更新速度
通常のバンドラではファイルが変更されたときにバンドル全体を再構築してWebページをリロードする必要がある.
これの対策としてHMR(ホットモジュールリプレースメント)という画面の再描画なくJSの変更をブラウザに適用できる仕組みが用意されているバンドラも多くあり,実際に開発者体験は改善する.
しかし,HMRでもアプリケーションが大きくなるにつれ更新速度が悪化する.
viteではHMRをネイティブESM上で行うので高速
全然わからない.わからない理由がネイティブESMを理解していないからな気がするのでその辺も調べてみる.
こいつを読んでみると
現在のフロントエンド開発ではソースコードをそのまま配布するのではなくビルドが必要でブラウザはビルドによって得られた成果物を読み込む(これをやるのがBabel, webpack, esbuildなど).
ビルド時にバンドラによってimport, exportで繋がった複数のjavascriptファイルが一つのファイルにまとめられる(これがバンドル)
この状況を打破するのがNative ESMでビルド後の成果物にもES Modulesの利用が含まれる
これのメリットは二つの問題の解消にある
ビルドパフォーマンスの問題
バンドルという工程がそもそも結構遅い
アプリ全体の内容を含むコードを生成することになるのでアプリのサイズに依存して遅くなる
開発中はファイル変更後に保存して,再バンドルする運用が主流であり,現在のソースをビルドした成果物をブラウザで開いて動作を確認しながら開発する
変更の影響を即座にブラウザに反映する機能としてHMRがあり,全体リロードを避けて効率化できる
しかし,それでもアプリサイズがデカくなるとバンドルは遅くなり,バンドルを繰り返す開発中のストレスになりうる
これがそもそもバンドルをしないNative ESMによって解消される.実際はソースファイルにimport, exportがある場合はHMRの対応のためにimport先をちょっと書き換える程度の変換がサーバーで行われるが,それほど時間はかからない
実行時パフォーマンスの問題
現在のバンドラによる成果物には,元々のソースファイルにあったimportをエミュレートする機能が含まれている.(これはES Modulesが使えない環境でもコードを実行できるようにするため)
これにより,バンドラによるモジュールグラフの解釈が行われた上でバンドルされたJSをブラウザが実行するので無駄がある
つまり,現状はモジュールグラフをバンドラのランタイムで解釈してるため,ブラウザが直接解釈するよりパフォーマンスが劣っている.
したがってNative ESMを使うことで高速化を目指せる...となるほど単純な話ではない
開発Native ESM時代ではimport, exportを含むコードをモジュールグラフの形で配信していた.がこれが許されるのは通信時間をほぼほぼ無視できるからであって,実際にはモジュールグラフを配信するのはパフォーマンス上問題がある.
どのモジュールを読み込むべきかはモジュールグラフを読み込まないと決定できず,何往復もすることになる.
原則1往復目でHTMLが帰ってきて,そこに乗っているURLのファイルを2往復目で取得する.
これに則るなら2往復目に全てのモジュールグラフをまとめて送る必要があり,元のソースコードそのままのモジュールグラフを先読みするには大量のファイルを読む必要がある(ここが結構謎ポイント)
と長くなったが,とりあえずNative ESMに対応することで開発環境では少なくとも開発スピード(正確にはコードを保存してからその内容を確認するまでのスピード)が向上することがなんとなくわかった.そして,それがviteによって可能になっていることがなんとなくわかった.
ちなみにこの人の解釈が少し参考になった.
最後にviteをビルドツールの歴史に沿って紹介しているスライドがあったのでこれを載せて締めとする.