スクリーンショット_2019-10-04_16

Angularでバンドルサイズを80%削減するためにやったことまとめ

結論

webpack-bundle-analyzer使おう

変更前の状態

Angular7(Renderer2)

$ npm run ng -- build --prod
Date: 2019-10-03T05:28:34.446Z
Hash: 0b42e7afd2f0a984f511
Time: 98170ms
chunk {0} runtime.26209474bfa8dc87a77c.js (runtime) 1.41 kB [entry] [rendered]
chunk {1} es2015-polyfills.c5dd28b362270c767b34.js (es2015-polyfills) 56.4 kB [initial] [rendered]
chunk {2} main.9e81bf5125d11d4d5f7a.js (main) 6.7 MB [initial] [rendered]
chunk {3} polyfills.ffd6decf11374fa22802.js (polyfills) 88.9 kB [initial] [rendered]
chunk {4} styles.496dbbf5b6fd1c5b5a53.css (styles) 73.6 kB [initial] [rendered]
chunk {scripts} scripts.e454dd0842cd3c67f3c5.js (scripts) 127 kB [entry] [rendered]
Initial: 6.917MB
Time: 98170ms

デカイ。
説明不要。

① Angular8(Ivy)を使う

Angular8にしてコンパイラを変えたらバンドルサイズが小さくなるってぼかぁ聞いたんだ

tsconfig.app.json

"angularCompilerOptions": {
  "enableIvy": true
}
$ npm run ng -- build --prod
chunk {0} runtime-es2015.b948044840398824f16e.js (runtime) 1.45 kB [entry] [rendered]
chunk {0} runtime-es5.b948044840398824f16e.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main-es2015.4283b24cd4e0771c647f.js (main) 6.22 MB [initial] [rendered]
chunk {1} main-es5.4283b24cd4e0771c647f.js (main) 6.29 MB [initial] [rendered]
chunk {2} polyfills-es2015.f40835661c1c4511f3cc.js (polyfills) 84.3 kB [initial] [rendered]
chunk {3} polyfills-es5.e30421bb0cc42e77e977.js (polyfills-es5) 170 kB [initial] [rendered]
chunk {4} styles.f0145d208870fdd892ba.css (styles) 73.7 kB [initial] [rendered]
chunk {scripts} scripts.e454dd0842cd3c67f3c5.js (scripts) 127 kB [entry] [rendered]
Date: 2019-10-04T03:20:36.803Z - Hash: c707323a1b2aa339696d - Time: 54424ms
Initial: 6.377MB(8%減)
Time: 54424ms(45%減)

ビルド時間が約半分になりました!すごい!
しかしイニシャルバンドルサイズはほぼかわらず…

② webpack-bundle-analyzerで分析

正攻法で行くぞォ

インストール

$ npm i -D webpack-bundle-analyzer

スクリプト登録
package.json

"scripts": {
  "analyze": "webpack-bundle-analyzer dist/browser/stats-es2015.json"
}

statsを出しつつビルド
プロダクションビルドするとconcatenatedになっちゃって中身わからんので解析用に--prodを外す

$ npm run ng -- build --stats-json

解析実行

$ npm run analyze

解析でたっ

スクリーンショット 2019-10-04 12.49.13

!?

スクリーンショット 2019-10-04 12.53.02

なんかscssでかない……tsファイルよりでかいのはさすがにおかしない……

スクリーンショット 2019-10-04 12.54.22

そんな

スクリーンショット 2019-10-04 12.54.39

まさか

スクリーンショット 2019-10-04 12.54.57

オアー

スクリーンショット 2019-10-04 12.58.11

ほとんどすべてのscssにimportしてるvariables、の中で143KBの@angular/material/_theming.scssがインポートされていたのでした

③ scssのimport修正

variablesでのthemingのimportをなくしてみる

$ npm run ng -- build --prod
chunk {0} runtime-es2015.b948044840398824f16e.js (runtime) 1.45 kB [entry] [rendered]
chunk {0} runtime-es5.b948044840398824f16e.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main-es2015.68a7321f2a5c21bb4928.js (main) 1.27 MB [initial] [rendered]
chunk {1} main-es5.68a7321f2a5c21bb4928.js (main) 1.35 MB [initial] [rendered]
chunk {2} polyfills-es2015.f40835661c1c4511f3cc.js (polyfills) 84.3 kB [initial] [rendered]
chunk {3} polyfills-es5.e30421bb0cc42e77e977.js (polyfills-es5) 170 kB [initial] [rendered]
chunk {4} styles.66ace95ede0b65a04357.css (styles) 73.7 kB [initial] [rendered]
chunk {scripts} scripts.e454dd0842cd3c67f3c5.js (scripts) 127 kB [entry] [rendered]
Date: 2019-10-04T04:21:32.340Z - Hash: 5edcbdc05e422c71e20c - Time: 29950ms
Initail: 1.427MB(80%減)
Time: 29950ms(69%減)

バンドルサイズが8割減!これでしたね!

この状態で解析してみます

スクリーンショット 2019-10-04 13.12.54

コンパイラーとかはプロダクションビルドすれば消えるのでいいとして、ちょっとまだでかい奴がいる

スクリーンショット 2019-10-04 13.13.19

こちらはグローバルのスタイルを巻き込んでいたので修正

-@import "../../../../../src/styles";
+@import "../../../../../src/scss/variables";

ファイルサイズのバランスが良くなりました

スクリーンショット 2019-10-04 13.19.08

これをプロダクションビルドするとこんなかんじに

スクリーンショット 2019-10-04 13.21.48

④ rxjsのインポート修正

バンドルサイズ問題でよく槍玉に挙げられるrxjsですが、6系なら `from 'rxjs'` でもツリーシェイキングが効いてるそうでimportの書き方を変えてもそこまで容量は変わりませんでした。
`from 'rxjs/internal/operators'` の削除はちょっとサイズ減ったので入れておく。

tslint.json

"import-blacklist": [
  true,
  "rxjs/Rx",
  "rxjs/internal/operators"
]
-import {map, catchError} from 'rxjs/internal/operators';
+import {map} from 'rxjs/internal/operators/map';
+import {catchError} from 'rxjs/internal/operators/catchError';
$ npm run ng -- build --prod
chunk {0} runtime-es2015.b948044840398824f16e.js (runtime) 1.45 kB [entry] [rendered]
chunk {0} runtime-es5.b948044840398824f16e.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main-es2015.0c8e2d679f3620397b74.js (main) 1.18 MB [initial] [rendered]
chunk {1} main-es5.0c8e2d679f3620397b74.js (main) 1.25 MB [initial] [rendered]
chunk {2} polyfills-es2015.f40835661c1c4511f3cc.js (polyfills) 84.3 kB [initial] [rendered]
chunk {3} polyfills-es5.e30421bb0cc42e77e977.js (polyfills-es5) 170 kB [initial] [rendered]
chunk {4} styles.66ace95ede0b65a04357.css (styles) 73.7 kB [initial] [rendered]
chunk {scripts} scripts.e454dd0842cd3c67f3c5.js (scripts) 127 kB [entry] [rendered]
Date: 2019-10-04T06:41:31.109Z - Hash: 5af612d5047dd4be37e0 - Time: 31725ms
Initial: 1.337MB(81%減)
Time: 31725ms(68%減)

このくらいでよいだろうか!budjet warningの2MB超えていないし!

chromeのデータセーブモードだと5MB以上だと落とせなくなってしまうのだそうです。

⑤ 適切にモジュール切ってlazyloadingする(したい)

これはまだ未着手です(タイトル詐欺)
プロジェクト作り始める時にlazyloadingできるようにモジュール切ろう!次からは!!!

時間をもらえたらリファクタできるかもしれないな

追記(2019/10/11):やりました


この記事が気に入ったらサポートをしてみませんか?