angular

Angular8のDefferential Loadで作られたPolyfill抜きJSがブラウザに読み込まれるまでを観察してみる

投稿日:2019年7月9日

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に展開されて処理されなくなることも含めると読み込み速度は幾分か速くなっているはずです。

これくらいならまだ誤差の範囲かも知れませんが、カスタマイズの余地があること、ロードを速くする為のツリーシェイキング以外の仕組みが標準的に用意されたことが嬉しいです。

-angular
-

執筆者:

関連記事

compodocでAngularプロジェクトのビジュアルなドキュメントを自動生成する

Java、C、Pythonのドキュメントを自動生成する際にDoxygenを使えばクラス図や呼び出し図、呼び出され図を作れて便利です。 しかしDoxygenはTypescriptには対応しておらず、.t …

正規表現結果をHTMLコード化してマッチ部分をハイライト表示

やりたかったのは「Rubular」が提供してくれるマッチした部分をハイライトしてくれる機能。 https://rubular.com/ ちょっとしたツールにこういう機能を入れようと思ったのですが、ニー …

Angular11から12にアップデートしたらng serveがproductionモードで起動するようになってしまう

既存のAngular11のプロジェクトを12に上げた際に発生。 目次1 環境2 事象3 原因4 対処5 根本原因6 まとめ 環境 Windows 11Node.js 14.15.1Angular13リ …

AngularアプリをPlaywright、 Jestテストし、カバレッジをマージする(V8編)

前回はistanbulでinstrumentしたAngularアプリに対してPlaywrightテストをし、カバレッジを計測しました。 One IT ThingAngularアプリをPlaywrigh …

Angular4.4のHTTP通信処理にタイムアウトを設定をすると「timeout is not a function」エラーが発生する

目次1 事象2 原因3 対処4 まとめ 事象 Angular4.3で追加されたHttpClientModuleに移行せず、HttpModuleを使い続けているアプリで、とある理由からpackage-l …

 

shingo.nakanishi
 

東京在勤、1977年生まれ、IT職歴2n年、生涯技術者として楽しく生きることを目指しています。デスマに負けず健康第一。