JavaScript (Node.js)のビルドは効率化と互換性を保っている話

技術発信
この記事は約6分で読めます。

毎日、Node.js(あるいはBun?)をシバいているエンジニアさんこんにちは。
今回の話は普段我々があまり意識をしていないNode.js系におけるビルドの話になります。
JavaScriptってブラウザネイティブで動くはずなのになぜビルドする必要があるのでしょうか?
他言語のビルドの話も通づるところはありますが、入門編として以下の話を目に通しておくとJavaScriptアプリをわざわざビルドすることに対しての理解がより深まると思います。

アプリケーションのチャンク戦略

Minify

Node.jsにより、ライブラリーを簡単に導入できるようになり勢いを増したJavaScript。
しかし、ここで大きな問題に直面します。
JavaScriptのファイル容量が多すぎ問題
ライブラリーをどんどん入れられるようになるとその分だけJavaScriptの容量が肥大化して、パフォーマンスに影響を及ぼすことになります。
ここで取った一つの戦略はJavaScriptを圧縮することです。
仕組みは難しいですが概念としては簡単です。
例えば”hogehoge”という変数を”h”と縮めたり、不要な改行やインデントを削除するだけです。

バンドル

もう一つ困ったことが発生します。
それはJavaScriptのファイルが多すぎる問題です。
これはhttp1.1の仕様ですが、1つのURL(オリジン)に対して2つのファイルを送受信できるものです。(Chromeは行儀悪く6つ)
つまり、JavaScriptを何個も受ける取ると通信的なオーバーヘッドが生まれるわけです。
このオーバーヘッドを無くすために出来るだけ無駄なく一つのファイルにまとめてしまうのがバンドルです。

bundle.png

参考

Why am'I using the webpack tool?
Everyone today is using webpack tool. When we enter the webpack website the first information that we...

チャンク分割

しかし、前述のバンドルで満足してしまうと特にSPAでは足枷となることになります。
HTTP1.1ではJavaScriptのファイルを出来るだけまとめてしまうことで高速化を行ってましたがHTTP2で送受信の多重化ができるようになりました。
このことで今度はJavaScriptのオーバーヘッドのほうが深刻な問題となりました。

  • JavaScriptのファイルが読み込まれるまでページを表示できない
  • ページに不要なJavaScriptもバンドルされている分、読み込みに時間がかかる

このため、次に効率良くまとまったJavaScriptを分割してしまいます。
せっかくまとめたのに

React LazyImport

const SomeComponent = lazy(load)

Vue LazyLoading

const Foo = () => import('./Foo.vue')

rollup(ビルドツール)manualchunks

({
	manualChunks: {
		lodash: ['lodash']
	}
});

他にもありますが、上記を駆使して効率よくJavaScriptを分割します。

チャンク戦略まとめ

実はたったの3ステップでJavaScriptアプリのパフォーマンスは最適化できます。

  1. バンドル(ライブラリの依存関係を解決・整理してまとめる)
  2. チャンク分割(効率よくファイルを分ける)
  3. Minify(JavaScriptのファイルサイズを削減する)

たとえば、私の簡単なポートフォリオサイトでもチャンクを画像化すると以下になります。
https://github.com/patatan168/portfolio_front

image.png
ポートフォリオのチャンク

Node.jsの互換性

ECMAScript

image.png

ECMAScriptとはEcma Internationalという国際的な標準化団体が制定したJavaScriptの標準規格(ECMA-262)のことを示します。
ブラウザ乱立時代、JavaScriptの仕様がブラウザごとに大きく異なりました。
そのため、ブラウザによっては誤作動が多発し、JavaScriptの信頼は地に落ちていました。
これを解決するために中立なEcma Internationalという団体により、各ブラウザのJavaScriptの仕様を統一することにしました。
現在でも以下のようにJavaScriptのエンジンは異なりますが、ECMAScriptのおかげで、昨今のJavaScriptはどのブラウザでも安定して動作するようになっています。

2026年 主要ブラウザのエンジン

毎年更新されるECMAScript

StandardDate
EcmaScript 1stJune 1997
EcmaScript 2ndAugust 1998
EcmaScript 3rdDecember 1999
EcmaScript 5thDecember 2009
EcmaScript 5.1thJune 2011
EcmaScript 2015June 2015
EcmaScript 2016June 2016
EcmaScript 2017June 2017
EcmaScript 2018June 2018
EcmaScript 2019June 2019
EcmaScript 2020June 2020
EcmaScript 2021June 2021
EcmaScript 2022June 2022
EcmaScript 2023June 2023
EcmaScript 2024June 2024
EcmaScript 2025June 2025
EcmaScriptバージョン一覧 2025まで

上記の細長い表のように
ECMAScriptは2015年以降、毎年6月にアップデートされています。
何がどう変わったのか毎年仕様を追うのがすごく大変ですね…。

Babel

BaBEL

毎年更新されるECMASCript。
仕事熱心なのは良いのですが、これもなかなかの弊害を生んでいます。

  • JavaScriptのエンジンが最新の規格に対応していない場合がある
  • 古いバージョンのブラウザでは最新の記法が動作しない

これを解消するJavaScriptのコンパイラーBabelが登場しました。
Babelの役割は以下になります。

  • 新しい規格の記法を古い記法に変換する
  • TypeScriptやフレームワーク特有の記法をJavaScriptに変換する

Babelは機械語に変換をするコンパイラーと異なり、
JavaScript=>JavaScriptの変換です。
人によっては同じ言語同士で変換しているのでコンパイラーと区別するために、
トランスパイラーと呼んでいる人もいるようです。
特に組み込み系のシステムでは、お客様のブラウザーが古いこともあるので、Babelを導入して、環境によるトラブルを避ける用途が期待されます。

互換のまとめ

  • ECMAScriptのお陰でどのブラウザでも均一にJavaScriptが動作するようになった
  • ECMAScriptは毎年更新される
  • 仕様が毎年更新されるので、古い規格に変換するコンパイラーが登場した

ECMAScriptのお陰でJavaScriptは広く使われるようになりました。
しかし、毎年規格が更新されるので一部のシステムでは互換性に配慮する必要がありました。
その問題を解決するためにBabelという素晴らしい技術が発明されることになりました。

全体のまとめ

いかがでしたでしょうか?
JavaScriptをわざわざコンパイルする意味は、ライブラリのチャンク戦略や互換性を上手いことやっているんだなと掴んでいただければOKです。
他にも例えばライブラリ独自のファイル形式 (JSX 、Vueなど)をコンパイルするというのもありますが、記事を書いている途中にどうやってこの2つはJavaScriptに変換しているんだ・・・というのに興味を持ったので、そこにもスポットライトを当てていきたいと思います。

タイトルとURLをコピーしました