「それに webpack がやってくれてる仕事は、単にモジュールの依存関係を解決してファイルをひとつにまとめることだけじゃない。主なものをざっと挙げるとこれくらいはある」
- Minify …… 空白文字やコメント、実行されないコードやコンソール出力などを削除、変数名や関数名を短縮、条件文や宣言文を簡略化するなどして、スクリプトファイルの容量を最小限に圧縮する
- Tree Shaking …… どこからも参照されていないモジュールを検出してバンドル対象から外し、出力ファイルの容量を削減する
- 画像データのインライン埋め込み …… 画像ファイルを『データ URL[1]』としてドキュメントにインラインで埋め込む(※ CRA のデフォルト設定では 10KB 以下の画像ファイルはデータ URL 化される[2])
- コード分割 …… モジュールの共有度合による自動分割に加え、開発者がアプリケーションの UI や規模を考慮しつつ、バンドルファイルを適切な粒度に分割し、それぞれが適切なタイミングで読み込まれるようにできる
- キャッシュ管理 …… ビルド時に出力ファイルの名前に差分単位でユニークな ID を付与することで、ブラウザキャッシュが適切に使われるようにし、かつキャッシュが残ることによる挙動の不具合を予防する
「こんなに!?」
「これだけじゃないよ。たとえば ES2015+ のコードをモダンブラウザにネイティブ実行させるより、Babel で ES5 にコンパイルしたコードのほうが往々にしてパフォーマンスがよくなる。
なぜかというと、コンパイルの対象が個々のファイルではなくプロジェクト全体で最適化され、かつ出力されるコードが JavaScript エンジンにとって解釈しやすいものになってるから。これは TypeScript のコンパイラも同様だね」
「ふむふむ」
「webpack を始めとする最新のモジュールバンドラがやっているのは、もはやネイティブアプリのビルドと遜色ない作業であって、ビルド先がバイナリコードかテキストコードかのちがいでしかない。
そのターゲットが Android アプリなら ARM 系 CPU の上で動く Android OS なのと同様、モダンフロントエンド開発ではそれがネットワークの向こうにある V8[3] や Nitro[4] で動いてるブラウザというだけの話なんだよ」
「うーむ。私、フロントエンドをなめてたかもしれません……。そんな次元の話なんですね」
「Web では見たまま動くのが正義だと考えてる人も多いけど、純粋にアプリケーション開発者としての立場からなら、冗長なテキストデータである HTML や CSS のほうがよっぽど『過渡期の技術』じゃない?
ブラウザはただのアプリケーションの実行環境であって、純粋にパフォーマンスを考えるなら媒体はバイナリデータのほうがいい。みんな好きな言語で効率よく開発して、ビルドしたバイナリデータをブラウザに実行させるのが理想でしょ。技術がそれに追いついてなかったり、SEO とかのレガシーな状況がそれを許さないだけで」
「そんなふうに考えたことがありませんでした。なるほど、いわれてみればそうですね」
「ちょっと話題が未来のほうまで飛びすぎたけど、とりあえず今の私たちは裏で webpack がやってくれていることに感謝しつつ、import
や export
を書けばいいんだよ。
ただ webpack があまりにも便利すぎるせいで npm パッケージの ES Modules 化が遅々として進まず、CommonJS や AMD がいつまでも消えずに残ってしまってる状況があるんだけどね……」
-
Google が開発するオープンソースの JavaScript エンジンであり、JIT コンパイル(ソフトウェア実行時にコードのコンパルを行う)を介して動作する仮想マシンの形を取る。Google Chrome や Microsoft Edge といった Chromium ベースのブラウザ、Node.js や Deno などのサーバサイド JavaScript ランタイムに採用されている。 ↩︎
-
Apple 製のブラウザである Safari のバージョン 4 以降に搭載されている JavaScript エンジン。JIT コンパイラと LLVM(コンパイル時やリンク時、実行時などあらゆる時点でプログラムを最適化するよう設計されたコンパイラ基盤)を採用しており、高速に JavaScript を実行可能。 ↩︎