【Angular6】angular-cli を拡張してMoment.js の locale を落とし bundle サイズを削減する

# はじめに

**この記事を実践して得られる効果**

（なんの対策もなく）Moment.js を利用しているプロジェクトの bundle サイズを 400kb 削減します（Gzip: 50kb）

**この記事の概要**

先日、angular のコミュニティにて [ngx-build-plusでCLIのwebpack設定をカスタマイズできそうな件](https://spectrum.chat/thread/35b54280-c10f-4a9e-8c21-8f5f7ec0bf4b) というスレが立ち、その中で **angular-cli を拡張して Moment.js の locale を分解できそう** というコメントを見かけたため、実際に試してみることにしました。

この記事では、プロジェクトの bundle ファイルを可視化して容量を圧迫している原因を発見、解消するまでを一連の流れとして紹介します。
今回は、その原因を「Moment.js の locale ファイルを無駄に読み込んでいること」に絞って進めていきます。

# bundle ファイルの可視化

## [webpack-bundle-analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer)

webpack-bundle-analyzer は、bundle ファイルを解析し、どの要素がどのくらいの容量をしめているのか可視化してくれるツールです。
フロントエンドの処理が複雑化している昨今では、必須ツールとなりつつあります？
（seed プロジェクトに組み込まれているのをチラチラ見かけるようになってきた

![image.png](https://qiita-image-store.s3.amazonaws.com/0/41793/bc3a519d-c373-808b-4be5-aa1a06db4b3b.png)

## webpack-bundle-analyzer の導入

### install

```console
npm install --save-dev webpack-bundle-analyzer
```

### alias の設定

```json:package.json
"scripts": {
    ...
    "build:analyze": "ng build --prod --stats-json",
    "analyze": "npm run build:analyze && ./node_modules/.bin/webpack-bundle-analyzer dist/path/to/stats.json"
    ...
}
```

### 実行

```console
npm run analyze
```

### 確認

自分が担当しているプロジェクトだと、最適化前の main.bundle はこんな感じでした...
ちょこっと使ってるだけの Moment.js が結構なスペースを占領しています。
そしてその大部分を占める locale は、曜日 や ~分前 といった表記を地域ごとに最適化してくれるので便利な機能ではあるのですが、それを使う機会は意外と少ないかと思います。
このプロジェクトでも使っていませんでした。

<img src="https://qiita-image-store.s3.amazonaws.com/0/41793/9366ec38-bcbd-41e5-b9fc-97d64eebfe8e.png" width="400">


![名称未設定-1.png](https://qiita-image-store.s3.amazonaws.com/0/41793/0d86f2d0-33a2-0f34-edce-9d1cf198c19c.png)

はい、駆逐します

# angular-cli のビルドスクリプト拡張

## [ngx-build-plus](https://github.com/manfredsteyer/ngx-build-plus)

冒頭でもチラっと触れましたが、CLI の webpack 設定をカスタマイズするためのライブラリです。
今回のように特定の処理を追加したいだけの場合は、拡張用の webpack.config を作成し、ビルド時に指定することで、CLI のビルドをカスタマイズすることができます。
また、[公式のサンプルリポジトリ](https://github.com/manfredsteyer/ngx-build-plus/tree/master/sample) のようにビルドスクリプトをフルカスタマイズすることもできるようです。

## ngx-build-plus の導入

### install

```console
npm install ngx-build-plus --save-dev
```

※ 6/12 時点での最新バージョンは 1.0.2 のようですが、エラーが発生して実行できなかったため、しばらくは 1.0.1 に固定して使った方が良いかもしれません。

### webpack 拡張設定の追加

```js:webpack.extra.js
const webpack = require('webpack');

module.exports = {
    plugins: [
        // Ignore all locale files of moment.js
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    ],
};
```

### angular.json の修正

```diff:angular.json
...
"architect": {
    "build": {
-       "builder": "@angular-devkit/build-angular:browser",
+       "builder": "ngx-build-plus:build",
        "options": {
        ...
```

### alias の修正

```diff:package.json
"scripts": {
    ...
-   "build:analyze": "ng build --prod --stats-json",
+   "build:analyze": "ng build --prod --extraWebpackConfig webpack.extra.js --stats-json",
    "analyze": "npm run build:analyze && ./node_modules/.bin/webpack-bundle-analyzer dist/path/to/stats.json"
    ...
}
```

### 実行

```console
npm run analyze
```

# 結果

<img src="https://qiita-image-store.s3.amazonaws.com/0/41793/534edf82-5caf-1644-5174-c30907c3e7b1.png" width="400">

先程まであれだけ存在感のあった Moment.js が locale を落としたことによりずいぶんと小さくなりました。


## 詳細

**before**

<img width="244" alt="スクリーンショット 2018-06-12 15.08.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/41793/38595b78-7cdf-9f1f-ebaa-197f7caf13ae.png">

↓

**after**

<img width="269" alt="スクリーンショット 2018-06-12 15.08.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/41793/886edabc-9d9b-6c37-108c-0b2db2220903.png">

---

Moment.js にズームアップして確認してみると、通常時のサイズが 530 → 140 となり約 400kb の削減。
Gzip 圧縮時でも 70 → 16 で 約 50kb の削減ができました。

# 終わり

angular のプロジェクトは angular-cli によって面倒な開発環境をほぼ意識せずに開発することができます。
一方で、ビルドスクリプトはブラックボックス化されプロジェクトごとに細かいチューニングを行うことが難しい状況でした。

しかしこれからは、[ngx-build-plus](https://github.com/manfredsteyer/ngx-build-plus) を利用することで公式のビルドに乗っかりつつ、細かいチューニングもしていけそうですね。
今回利用した Moment.js の bundle サイズを削減する以外にも まだまだ使い道があると思いますので、ぜひ一度お試し下さい。
導入も簡単で素晴らしいツールでした (\*´∀`\*)


# 参考

https://qiita.com/jimbo/items/95da1c223ad25a33ed16
https://qiita.com/yuki-takei/items/de23633fe2cfbab9a08c