【Node.js】bundleサイズは大事って話

#サービスの動作が遅かった
最近，アーチャー伝説ってスマホアプリ専用の[【マルチ募集掲示板サービス】](https://archer-duo.herokuapp.com/)をリリースしました．

技術としては，Node.js/React/TypeScript/Express/Webpackを使用しました．このサービス，募集スレッドのリアルタイム更新をアピールしてるんですが，その肝心のbundle.jsが動き出すのが遅いんですよね．

そこでSSR(Server Side Rendering)について調べてたら[こんなサイト](https://www.publickey1.jp/blog/17/server_side_renderingserver_side_rendering_ng-japan_2017.html)が出てきて，めっちゃわかりやすいやんけ！と．要するにNode.jsってすごいし早いけど，やっぱSSRしない方が動作は早いよねと．でもSEOの観点とUX考慮するとまあSSRした方がいいよねと．

そこで重要になるのがjsの読み込み速度．今回Webpackを使ってるのでここをなんとかせねば！<font color="OrangeRed">Webpackってjs全部ひとまとめにしてくれてめちゃくちゃ便利な反面，そのbundleされたjsファイルに対して何もしなかったらかなり重いんです．</font>

#bundle.jsを小さくするために！
今回ReactのMaterial-UI使ってたり，Express.js使ってたりと，小さく出来そうなとこはいろいろありそうでした．サイズ小さくするために，ちょっとめんどくさい書き方になったりしますが，これはユーザビリティ考えると致し方ありませんね．ちなみに下の画像がなーんにも手を加えずbundleしてた時のサイズ．1.29Mbもあります．（BundleAnalyzerPluginって神様）ちなみにこれjs読み終わるのに10秒くらいかかってました....
<img width="651" alt="スクリーンショット 2020-04-17 21.51.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458915/afb023bc-26ec-85fb-f317-535b8f9fbbd5.png">
で，この中でも，Material-UIが997Kb...これだけでbundle.js全体の8割弱占めてる...<font color="OrangeRed">Material-UI使う時は必ず注意すべきですね</font>
<img width="532" alt="スクリーンショット 2020-04-17 21.52.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458915/89d6546c-bc54-68da-c548-07d8afbc1c3a.png">
ささ，bundleサイズ小さくしていきましょうか．

##Express.js
```javascript
import compression from 'compression';
app.use(compression());
```
これだけでbundle.jsをgzipで圧縮してくれるんです．便利すぎて笑

##Material-UI
```javascript
//Good
import AppBar from '@material-ui/core/AppBar';
//Bad
import { AppBar } from '@material-ui/core';
```
上のように書き換えます．それだけです．僕の場合は多い時は1コンポーネントに10個ほどモジュールをimportしてたので，かなりめんどくさい...下の書き方だったら一行でほとんどimportできますから．
で，なぜ下はダメなのか．これ直接node_modulesディレクトリから探せば一目瞭然ですが，<font color="Red">下の場合だと@material-ui/core全部インストールしてきてそっからAppBarを探すんですよね．</font>そりゃ容量食いますね．

##CSS
```javascript
const sheets = new ServerStyleSheets();
renderToString(
  sheets.collect(
    React.createElement(component)
  )
);
const css = (sheets.toString()).replace(/\s+/g, "");
```
僕の場合はMaterial-UIで使われるcssもSSRでテンプレートエンジン(pug)に渡す必要があったので，cssを文字列で渡すんですよね．で，cssとかjsの読み込みに空白とか改行，コメントが入ってたらそれまた遅くなります．なのでここではスペースを全て削除することでcssを圧縮しました．

#bundleサイズのビフォーアフター
bundleサイズ438Kb！
<img width="481" alt="スクリーンショット 2020-04-17 21.52.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458915/039596a7-1172-f852-95ee-75b3aafbc85e.png">
Material-UIも258Kbに！
<img width="427" alt="スクリーンショット 2020-04-17 21.52.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458915/e639c5e3-a451-b768-2744-627ea64b9554.png">

結果，<font color="Red">800Kb以上圧縮できましたね！</font>6.5割程削減できたのかな？

[【マルチ募集掲示板サービス】](https://archer-duo.herokuapp.com/)の読み込みもだいぶ早くなりました！ストレスは感じないですね！Lighthouseで測定したら，<font color="Red">Performanceが60点台から96点になりました！！</font>
![スクリーンショット 2020-04-17 22.35.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458915/e460325e-c64f-b3e9-618a-f2d62390636a.png)
アクセシビリティも改善したいのですが，サードパーティコードの影響を削減ってよくわからなくてわからないです....[このサイト](https://www.publickey1.jp/blog/17/server_side_renderingserver_side_rendering_ng-japan_2017.html)によるとNode.jsってサーバのメインループをブロックするらしくて，そのことかなと思うのですが...誰か教えていただけると幸いです！
![スクリーンショット 2020-04-17 22.39.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458915/7fb0d977-b23b-eae2-3bac-589ddf6b2f3e.png)

#まとめ
Webpackとかでbundleしたり，いろんなモジュール使うならサイズ小さくしようってことです！