「現代魔術JS×Web設計」のイメージと概念〜ビルド編〜

# はじめに
半年前ぐらい前にアニメ「葬送のフリーレン」を見て、この際にふとエンジニアとして見過ごせない概念がありました。  
**「魔術はイメージの世界」**  
私はジュニアプログラマーながら激しく同意したのを覚えてます。  
Web設計はどんどん肥大化と複雑化していくもので、それに抗うための技術が発生するなどして…中々イメージが捉えづらいと思います。  
本記事はそんな捉えづらい概念をご紹介していければと思います。

:::note info
初投稿のジュニアプログラマーです。
ご指摘がありましたら、ビシバシお願いします。
:::

# Node.js

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690326/dac32338-d511-13dd-dd55-901cd23ca070.png)


Node.jsとは…単にGoogle Chromeをサーバーサイドで動かしてしまおうという技術です。
今までJavaScriptはブラウザサイドで動くものとして扱ってきました。
しかしサーバーサイドで動かせるようになるということはサーバー内のファイルにJavaScriptでアクセスできる事を指します。
つまり頭の良い人はこう考えました…

- Node.jsのおかげでJavaScriptでもライブラリを導入できるよね？
- PHPと同じようにサーバー内のDBもアクセスできるってこと！？

大きな革命ですね。
今や当たり前になってるNode.jsですが、本当は革命的なものであることを抑えとくと
Node.jsがいかに基礎的で重要なものかわかると思います。

# JavaScriptのビルド

## Minify

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

## バンドル

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

![bundle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690326/4f007793-3519-348b-c807-7b9cf8993394.png)

参考

https://dev.to/bruno8moura/why-am-i-using-the-webpack-tool-4h14


## チャンク分割

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

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

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

[React LazyImport](https://ja.react.dev/reference/react/lazy)

```js
const SomeComponent = lazy(load)
```

[Vue LazyLoading](https://v3.router.vuejs.org/ja/guide/advanced/lazy-loading.html#%E5%90%8C%E3%81%97%E3%82%99%E3%83%81%E3%83%A3%E3%83%B3%E3%82%AF%E5%86%85%E3%81%A6%E3%82%99%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%9B%E3%82%9A%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%AF%E3%82%99%E3%83%AB%E3%83%BC%E3%83%95%E3%82%9A%E5%8C%96)

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

[rollup（ビルドツール）manualchunks](https://rollupjs.org/configuration-options/#output-manualchunks)

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

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

## JavaScriptのビルド魔術(まとめ)

一番面倒な場合でも実は3ステップです。
使用率の多いReact、Vueをビルドする場合なので、
他のフレームワークの場合はもう少し複雑かもしれませんが。

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

たとえば、私の簡単なポートフォリオサイトでもチャンクを画像化すると以下になります。
うーん、これは魔術。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690326/ae2a9a3b-4aeb-5490-bcd1-061f8fdb708d.png)

# ECMAScriptとBabel

## ECMAScript

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690326/e894b0b4-92a4-001a-31e6-60cfbd531664.png)


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

| Web Browser | Rendering Engine | JavaScript Engine |
| --- | --- | --- |
| Chrome | Blink | V8 |
| Firefox | Gecko | SpiderMonkey |
| Safari | Webkit | JavaScriptCore |

## 毎年更新されるECMAScript

<details><summary>EcmaScriptバージョン一覧 2024年まで (Click me)</summary>

| Standard | Date |
| --- | --- | 
| EcmaScript 1st | June 1997 |
| EcmaScript 2nd | August 1998 |
| EcmaScript 3rd | December 1999 |
| EcmaScript 5th | December 2009 |
| [EcmaScript 5.1th](https://262.ecma-international.org/5.1/index.html) |  June 2011 |
| [EcmaScript 2015](https://262.ecma-international.org/6.0/index.html) |  June 2015 |
| [EcmaScript 2016](https://262.ecma-international.org/7.0/index.html) |  June 2016 |
| [EcmaScript 2017](https://262.ecma-international.org/8.0/index.html) |  June 2017 |
| [EcmaScript 2018](https://262.ecma-international.org/9.0/index.html) |  June 2018 |
| [EcmaScript 2019](https://262.ecma-international.org/10.0/index.html) |  June 2019 |
| [EcmaScript 2020](https://262.ecma-international.org/11.0/index.html) |  June 2020 |
| [EcmaScript 2021](https://262.ecma-international.org/12.0/index.html) |  June 2021 |
| [EcmaScript 2022](https://262.ecma-international.org/13.0/index.html) |  June 2022 |
| [EcmaScript 2023](https://262.ecma-international.org/14.0/index.html) |  June 2023 |
| [EcmaScript 2024](https://262.ecma-international.org/15.0/index.html) |  June 2024 |

</details>

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

## Babel

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690326/01df56b5-a340-66a1-35ac-69086c162550.png)

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

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

これを解消するJavaScriptのコンパイラー[Babel](https://babeljs.io/)が登場しました。
Babelの役割は以下になります。

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

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

## JavaScriptの互換魔術(まとめ)

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

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

# 次回予告

次回は遅延読み込みあたりをお話できればと思います。
人気が出れば出るほど私のモチベーションが上がりますので、良いなと思ったら「いいね」をお願いします！