Webpack?Create React App?No、Vite!! ~ ①コンパイル、バンドル、ビルドを理解しよう ~

# 前置き

昨今ではビルドツールの進化により、Webフロントエンド開発開発は大きく変化しました。以前は設定ファイルを詳細に定義したコンパイル、バンドル、ビルドといった作業が必要でしたが、最近では新しいツールが登場し、そうした設定を含む開発プロセスを大幅に効率化しています。一方で、**便利になったあまり、実際にビルドツールが内部的にどのようなことをしているのか見えにくくなった**ことも確かです。本記事から数回に分けて、そもそもJSにおけるコンパイル、バンドル、ビルドって？というところから、実際にwebpack,Create React App,Viteを用いてReactの開発環境構築をすることで、その中身や技術の凄みを体感していこうと考えています。

# アジェンダ
## ①コンパイル、バンドル、ビルドを理解しよう←今回

## ②webpackによるReact開発環境構築
以前は、webpackというビルドツールがReact開発環境のデファクトスタンダードでした。webpackは非常にパワフルで柔軟なツールであり、モジュールのバンドルやトランスパイル、リソースの最適化など、様々な機能を提供します。しかし、設定が複雑で初心者には敷居が高いという課題がありました。実際に開発環境構築することで、本来私たちが開発に辿り着くまでにどのようなプロセスを踏む必要があるのかを理解します。

https://qiita.com/Yuppe-jp-eng/items/27762672599e1d4cbfa0

https://qiita.com/Yuppe-jp-eng/items/371fafaf26d5fc6506f1

## ③Create React AppによるReact開発環境構築:
その後、Facebookが提供する「Create React App」が登場し、React開発の初心者や迅速なプロトタイピングにとって非常に便利なツールとなりました。Create React Appは、Reactプロジェクトのセットアップや設定を自動的に行い、簡単にReactアプリケーションの開発を始めることができます。設定の詳細を隠蔽することで、初学者でも短時間でReact開発を始めることができます。実際に環境を作ってその便利さを体感します。

## ④ViteによるReact開発環境構築とその技術的な凄み:
最近、Viteという新たなビルドツールが登場し、React開発環境の構築において注目を集めています。Viteは、開発サーバーにおいてHMR（Hot Module Replacement）を活用し、リアルタイムで変更を反映させることができます。さらに、ESモジュールを直接ブラウザに提供することで、開発時のビルドやバンドルの遅延を劇的に軽減しています。Viteは設定がシンプルで使いやすく、高速な開発体験を提供するため、多くの開発者に支持されています。その「爆速」ぶりを体感します。


# 対象読者
- 現状のReact開発環境に不満がある人
- そもそもwebpackとかCRAとかViteが何のためにあるのか曖昧な人
- Viteについてちょっと詳しくなりたい人

# やらないこと
- Viteを用いたプロジェクトの本番運用Tips等、より実践的な内容
- 各種ツールの設定値の詳細の解説

また、中身とかどうでもいいので**手っ取り早くReact勉強する環境が欲しいよ**という人は以下記事をご参照ください。
Docker,Vite,Dev Containerを使ってReact18の開発環境を構築したリポジトリを貼っています。

https://qiita.com/hiroki-yod/items/9b065f1b66ebb727f177


# 1.そもそもなぜこれらのツールが必要なのか?

これを理解するには、まず基本的には次の3つの動詞の意味をしっかりと理解する必要があります。
1. 「コンパイル」
2. 「バンドル」
3. 「ビルド」 


## 1-1.コンパイル(Compile)
> コンパイルとは、特定のプログラミング言語を用いて記述されたコンピュータープログラムを他の言語 (普通はコンピューターが実行できるバイナリ言語) を用いて記述された同じプログラムに形を変えることである。
> 

より砕けた説明だと「人間にとって分かりやすいソースコードをCPUが解釈できる機械語に翻訳する」というものもよく見かけますよね。
「コンパイルの説明をしろ」と言われたら上記の説明は何も間違っていませんが、とりわけJavaScriptとかを扱うときの「コンパイル」が指しているものをこのように解釈してしまうと、あまり釈然としない感じになります。

「別にJSって人間にも読めるし？ReactやTSだって勉強すれば読めちゃうよ？」となるわけです。

これに関しては、下記のようにより広義な意味で「コンパイル」を捉えると解決するかなと思います。

「**元のプログラムをシステムやアプリケーションの実行環境(ランタイムと言います)に合ったプログラムに変換すること**」

例えば、Pythonを使って書かれたアプリケーションを動作させるには、もちろんPythonの実行環境が必要ですよね。「Pythonの実行環境しかないのにPHP動かしたい」となると皆さん十中八九「いやいやそれは...笑」となるはずです。でもJSも同じです。JSを動かすにはそのためのランタイムが必要になります。

「でもブラウザってなんか特別そうじゃん？」

いいえ、**ブラウザもアプリケーション**です。そして一般にブラウザというアプリケーションはJavaScriptのランタイムを有しているため、私たちはブラウザ上でJSを動作させることができます。ここまで理解すればもうお分かりかと思いますが、JSにおける「コンパイル」[^1]は、**例えばReact(JSX)や、TypeScript(TS)をJSのランタイムを有する環境(ブラウザ,Node.js)で動かすための作業を指していた**わけです。

```mermaid

graph TD
    A(TypeScript TS File)
    C(JSX File)
    B(Transformed JavaScript JS File)
    E(Browser or Node.js)
    A -->|tsc Compiler| B
    C -->|Babel Compiler| B
    B --> E

```

## 1-2.バンドル(Bundle)
次にバンドルについて理解していきます。bundleには「束ねる」という意味があります。その名の通り「束ねる」のですが、何を束ねるのでしょうか。
次のようなHTMLファイルがサーバー間とどのような通信を生むかを考えてみます。
```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>複数のスクリプトファイル</title>
</head>
<body>
    <script src="script1.js"></script>
    <script src="script2.js"></script>
    <script src="script3.js"></script>
    <script src="script4.js"></script>
</body>
</html>

```
このファイルでは1~4のスクリプトファイルを読み込んでいます。このときのサーバーとのやりとりを簡単に図示すると以下のようになります。

```mermaid
sequenceDiagram
    participant Browser as ブラウザ
    participant Server as サーバー
    Browser->>Server: HTMLファイルを要求
    Server->>Browser: HTMLファイルを送信
    Browser->>Server: script1.jsを要求
    Server->>Browser: script1.jsを送信
    Browser->>Server: script2.jsを要求
    Server->>Browser: script2.jsを送信
    Browser->>Server: script3.jsを要求
    Server->>Browser: script3.jsを送信
    Browser->>Server: script4.jsを要求
    Server->>Browser: script4.jsを送信
```
基本的にscriptタグに何らかの指定をしない限り上から順番に同期的に読み込まれるため、当たり前ですがスクリプトの数だけサーバーへのリクエストが発生し、ネットワークパフォーマンス的によろしくないです。[^2]
そこで、バンドラーの登場です。バンドラーはこれらファイルの依存関係を考慮した上で一つのスクリプトファイルに束ね上げ、ネットワークパフォーマンスを最適化します。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>バンドルされたスクリプトファイル</title>
</head>
<body>
    <script src="bundle.js"></script>
</body>
</html>
```

```mermaid
sequenceDiagram
    participant Browser as ブラウザ
    participant Server as サーバー
    Browser->>Server: HTMLファイルを要求
    Server->>Browser: HTMLファイルを送信
    Browser->>Server: bundle.jsを要求
    Server->>Browser: bundle.jsを送信 (複数のスクリプトが1つにまとめられている)

```
のちに使用する**webpack**は基本的にこのバンドルのためのツールとして広く使われています。(packにも「束ねる」という意味がありますね)さらにバンドルを行えるということは、その前段階でモジュール化の恩恵を受けられるということです。一つの機械を作るときに、開発メンバーが分業せず同時に同じところをいじりながら作るのは大変です。部品ごとに分業体制をとるべきですよね。アプリケーションの開発もそれぞれが部品化していれば、あとはすり合わせさえしっかりすることで分業体制をとることができます。


## 1.3.ビルド(Build)
実はビルドに関しては、7割型説明が終わっていると言っても過言ではありません。というのもビルドは先に説明したコンパイルやバンドル、その他作業の総称のようなものだからです。
```mermaid
graph TD
    A[Build]
    B[Bundle]
    C[Compile]
    D[Other Tasks]
    E(Merge multiple files into one)
    F(Convert source code to executable code)
    G(Optimization, Minification, Linting etc.)
    
    A --> B
    A --> C
    A --> D
    B --> E
    C --> F
    D --> G
```
実際にwebpackを用いてこの作業を行うことで、より詳細にイメージができると思います。
次回は②webpackによるReact開発環境構築を扱って、実際にこれらのことをどのように実現するのか見ていきます。気になる方はぜひいいねやストックしてくださると、今後の励みになります。よろしくお願いします。


[^1]:とはいえ、本来の意味の「コンパイル」とはどうしてもずれてきてしまう部分はあるので、こうしたTypeScriptをJavaScriptにコンパイルするような、同レベル間の言語を翻訳することは「トランスパイル」や「クロスコンパイル」と呼び分けされていたりします。(https://developer.mozilla.org/ja/docs/Glossary/Compile)

[^2]:話を単純化するためにscriptが複数あることで生じる問題を「リクエストの数」の問題に限定しましたが、それとは別に「JSの実行タイミング」の問題や「DOMのレンダリングの遅延」の問題があります。それに関してはdeferやasyncを使うと一部解消することができますが、多くのファイルを扱う場合、依存関係を考慮しなければいけないことに変わりなく、面倒です。deferとasyncに関しては[こちら](https://qiita.com/phanect/items/82c85ea4b8f9c373d684)。