Angular単体では約30%の削減でした。
2019/05にリリースされたAngular8では、ビルド結果として生成されるバンドルファイルがES6(ES2015)対応しているモダンブラウザ用、とそうでないレガシーブラウザ用の二つ生成されるようになりました。(これら二つのJSが作られる過程を調べた記事ではありません)
前者の場合は古いブラウザ機能を補填する為のポリフィルが抜かれているのでサイズが小さくなっているはずです。ng newで作られるプロジェクト雛型で、ブラウザに読み込まれるまでの挙動を確認してみました。
目次
環境
- Windows 10
- Angular 8.1.0
- Node.js 10.16.0(Angular8が要求するNode.jsバージョンは10.9以上)
Angular8をインストールしてプロジェクトをビルド
グローバル汚染対策
グローバルにngコマンドを入れて既存の古いAngularプロジェクトに影響が出ると嫌なので局所的に入れます。
angular-pjディレクトリを親ディレクトリとして@angular/cliをインストール、ng new {プロジェクト}で作るディレクトリにも@angular/cliは自動で入るので、PATH環境変数に「./node_modules/bin」を入れておけば実行するngコマンドの場所、バージョンは使い分けられます。
C:\src\js\angular-pj>which ng
/cygdrive/c/src/js/angular-pj/node_modules/.bin/ng
C:\src\js\angular-pj\ng8sizetest>which ng
/cygdrive/c/src/js/angular-pj/ng7sizetest/node_modules/.bin/ng
Angular最新バージョンを確認してインストール
「npm info {モジュール名} versions」コマンドしてみると、2019/07現在では8.1.0が最新のようです。
C:\src\js\angular-pj>npm info @angular/cli versions
[ '1.0.0-beta.28.3',
'1.0.0-beta.29',
(snip)
'8.0.0-rc.4',
'8.0.0',
'8.0.1',
'8.0.2',
'8.0.3',
'8.0.4',
'8.0.5',
'8.0.6',
'8.1.0-beta.0',
'8.1.0-beta.1',
'8.1.0-beta.2',
'8.1.0-beta.3',
'8.1.0-rc.0',
'8.1.0' ]
npm install。-gは付けません。
C:\src\js\angular-pj>npm install @angular/cli@8.1.0
> @angular/cli@8.1.0 postinstall C:\src\js\angular-pj\node_modules\@angular\cli
> node ./bin/postinstall/script.js
+ @angular/cli@8.1.0
added 72 packages, removed 122 packages and updated 15 packages in 25.138s
一応バージョン確認。
C:\src\js\angular-pj>ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 8.1.0
Node: 10.16.0
OS: win32 x64
Angular: undefined
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.801.0
@angular-devkit/core 8.1.0
@angular-devkit/schematics 8.1.0
@angular/cli 8.1.0
@schematics/angular 8.1.0
@schematics/update 0.801.0
rxjs 6.4.0
このディレクトリのangularをng install @angular/cli@7.3.9とかで入れ替えてやれば色んなバージョンのAngularプロジェクトが直下ディレクトリに作れるようになります。
(*)余談ですが、Angular8からNode.jsの最低バージョンラインが10.9に上がったようです。8.11を使っていたら以下のエラーでたしなめられました。Node.js 10.16.0 LTSに上げて解決しています。
C:\src\js\angular-pj>ng --version
You are running version v8.11.1 of Node.js, which is not supported by Angular CLI 8.0+.
The official Node.js version that is supported is 10.9 or greater.
Please visit https://nodejs.org/en/ to find instructions on how to update Node.js.
Angular8プロジェクトを作成
angular8が入ったのでng8sizetestというプロジェクト名で作成します。
ルータ有り、SCSS。
C:\src\js\angular-pj>ng new ng8sizetest
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS [ http://sass-lang.com/documentation/file.SASS_REFERENCE.html#syntax ]
CREATE ng8sizetest/angular.json (3553 bytes)
CREATE ng8sizetest/package.json (1284 bytes)
(snip)
プロダクションビルドする
ソースは何も弄りません。プロジェクト雛型のまま挙動を見ます。
C:\src\js\angular-pj> cd ng8sizetest
C:\src\js\angular-pj\ng8sizetest> ng build --prod
ビルド結果資源を見てみる
distディレクトリ内資源を見てみます。
C:\src\js\angular-pj\ng8sizetest\dist\ng8sizetest のディレクトリ
2019/07/06 15:13 <DIR> .
2019/07/06 15:13 <DIR> ..
2019/07/06 14:01 23,612 3rdpartylicenses.txt
2019/07/06 14:01 5,430 favicon.ico
2019/07/06 14:01 790 index.html
2019/07/06 14:01 215,637 main-es2015.91103ba8cd8131647ea6.js
2019/07/06 14:01 248,900 main-es5.0666c047c6de5c9a073f.js
2019/07/06 14:01 37,298 polyfills-es2015.551225243b1eb435bb30.js
2019/07/06 14:01 115,451 polyfills-es5.7d557f3a1ecba44264aa.js
2019/07/06 14:01 1,440 runtime-es2015.d5623f03f1e64ac8e12f.js
2019/07/06 14:01 1,440 runtime-es5.a8c9c2928baa49aa82ad.js
2019/07/06 14:01 0 styles.09e2c710755c8867a460.css
10 個のファイル 649,998 バイト
2 個のディレクトリ 52,012,990,464 バイトの空き領域
main | polyfill | runtime-es2015.xxxxxxxxxxxxxxxxxxxx.js
が作られていて同じ名前の-es5ファイルよりもサイズが削減されていることが分かります。
次にindex.htmlでどう読み込んでいるのか見てみます。
(読みやすいように改行しています)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ng8sizetest</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.09e2c710755c8867a460.css"></head>
<body>
<app-root></app-root>
<script src="runtime-es2015.d5623f03f1e64ac8e12f.js" type="module"></script>
<script src="polyfills-es2015.551225243b1eb435bb30.js" type="module"></script>
<script src="runtime-es5.a8c9c2928baa49aa82ad.js" nomodule></script>
<script src="polyfills-es5.7d557f3a1ecba44264aa.js" nomodule></script>
<script src="main-es2015.91103ba8cd8131647ea6.js" type="module"></script>
<script src="main-es5.0666c047c6de5c9a073f.js" nomodule></script>
</body>
</html>
Angular7までは付いていなかった「type=”module”」が付いていました。ES6をサポートしているモダンブラウザはこれが付いているJSを読み込み、nomoduleが付いているものは読み込まない、という仕組みのようです。ここでロードするかどうかを切り分けているんですね。
ES5、ES2015どちらの資源が読み込まれるか確認してみる
ng serve –prod=trueで起動したHTTPサーバでは読み込む資源をAngaularがメモリ上で効率化するので正確なファイル名が分かりません。Angularとは無関係のhttp-serverコマンドでHTTPサーバを建てます。
C:\src\js\angular-pj\ng8sizetest> npm install -g http-server
C:\src\js\angular-pj\ng8sizetest> cd dist\ng8sizetest
C:\src\js\angular-pj\ng8sizetest\dist\ng8sizetest> http-server .
Chromeの開発者ツールで見てみると、ポリフィルが抜かれたes2015の資源が読み込まれ、サイズが大きいes5の資源は読み込まれていないことが確認出来ました。
削減率
Angular単体では364,351Byte – 252,935Byte = 計111,416Byteの読み込みサイズ削減、Defferential Load無し版と比較すると69.42%まで小さくなりました。
DOMに展開されて処理されなくなることも含めると読み込み速度は幾分か速くなっているはずです。
これくらいならまだ誤差の範囲かも知れませんが、カスタマイズの余地があること、ロードを速くする為のツリーシェイキング以外の仕組みが標準的に用意されたことが嬉しいです。