製品バンドルサイズを減らす方法は?


135

私は初期化されたシンプルなアプリを持っています angular-cli

3つのルートに関連するいくつかのページを表示します。3つのコンポーネントがあります。このページのIの使用のいずれかにlodashいくつかのデータを取得するために、角2 HTTPモジュール(RxJS使用してObservableSを、mapsubscribe)。単純なを使用してこれらの要素を表示します*ngFor

しかし、私のアプリは本当にシンプルであるにもかかわらず、私は(私の意見では)巨大なバンドルパッケージとマップを取得しています。私はgzipのバージョンについては話しませんが、gzipする前のサイズです。この質問は、一般的な推奨事項の問い合わせです。

一部のテスト結果:

ビルド

ハッシュ:8efac7d6208adb8641c1時間:10129msチャンク{0} main.bundle.js、main.bundle.map(main)18.7 kB {3} [初期] [レンダリング]

チャンク{1} styles.bundle.css、styles.bundle.map、styles.bundle.map(styles)155 kB {4} [初期] [レンダリング]

チャンク{2} scripts.bundle.js、scripts.bundle.map(scripts)128 kB {4} [初期] [レンダリング]

チャンク{3} vendor.bundle.js、vendor.bundle.map(vendor)3.96 MB [初期] [レンダリング]

チャンク{4} inline.bundle.js、inline.bundle.map(inline)0バイト[エントリ] [レンダリング]

待つ:そのような単純なアプリ用の10Mbベンダーバンドルパッケージ?

ng build --prod

ハッシュ:09a5f095e33b2980e7cc時間:23455ミリ秒のチャンク{0} main.6273b0f04a07a1c2ad6c.bundle.js、main.6273b0f04a07a1c2ad6c.bundle.map(main)18.3 kB {3} [初期] [レンダリング]

チャンク{1} styles.bfdaa4d8a4eb2d0cb019.bundle.css、styles.bfdaa4d8a4eb2d0cb019.bundle.map、styles.bfdaa4d8a4eb2d0cb019.bundle.map(styles)154 kB {4} [初期]

チャンク{2} scripts.c5b720a078e5464ec211.bundle.js、scripts.c5b720a078e5464ec211.bundle.map(scripts)128 kB {4} [初期] [レンダリング]

チャンク{3} vendor.07af2467307e17d85438.bundle.js、vendor.07af2467307e17d85438.bundle.map(vendor)3.96 MB [初期] [レンダリング]

チャンク{4} inline.a345391d459797f81820.bundle.js、inline.a345391d459797f81820.bundle.map(inline)0バイト[エントリ] [レンダリング]

もう一度待ってください。製品のこのような同様のベンダーバンドルサイズですか?

ng build --prod --aot

ハッシュ:517e4425ff872bbe3e5b時間:22856ミリ秒のチャンク{0} main.95eadabace554e3c2b43.bundle.js、main.95eadabace554e3c2b43.bundle.map(main)130 kB {3} [初期] [レンダリング]

チャンク{1} styles.e53a388ae1dd2b7f5434.bundle.css、styles.e53a388ae1dd2b7f5434.bundle.map、styles.e53a388ae1dd2b7f5434.bundle.map(styles)154 kB {4} [初期] [レンダリング]

チャンク{2} scripts.e5c2c90547f3168a7564.bundle.js、scripts.e5c2c90547f3168a7564.bundle.map(scripts)128 kB {4} [初期] [レンダリング]

チャンク{3} vendor.41a6c1f57136df286f14.bundle.js、vendor.41a6c1f57136df286f14.bundle.map(vendor)2.75 MB [初期] [レンダリング]

チャンク{4} inline.97c0403c57a46c6a7920.bundle.js、inline.97c0403c57a46c6a7920.bundle.map(インライン)0バイト[エントリ] [レンダリング]

ng build --aot

ハッシュ:040cc91df4df5ffc3c3f時間:11011ミリ秒のチャンク{0} main.bundle.js、main.bundle.map(main)130 kB {3} [初期] [レンダリング]

チャンク{1} styles.bundle.css、styles.bundle.map、styles.bundle.map(styles)155 kB {4} [初期] [レンダリング]

チャンク{2} scripts.bundle.js、scripts.bundle.map(scripts)128 kB {4} [初期] [レンダリング]

チャンク{3} vendor.bundle.js、vendor.bundle.map(vendor)2.75 MB [初期] [レンダリング]

チャンク{4} inline.bundle.js、inline.bundle.map(inline)0バイト[エントリ] [レンダリング]

だから、私のアプリを製品版にデプロイするためのいくつかの質問:

  • ベンダーバンドルがなぜそれほど巨大なのですか?
  • 木の揺れはによって適切に使用されていangular-cliますか?
  • このバンドルサイズを改善するにはどうすればよいですか?
  • .mapファイルは必要ですか?
  • テスト機能はバンドルに含まれていますか?私はそれらを製品に必要としません。
  • 一般的な質問:本番用にパックするために推奨されるツールは何ですか?多分angular-cli(バックグラウンドでWebpackを使用する)は最良のオプションではありませんか?もっと上手くできる?

Stack Overflowで多くのディスカッションを検索しましたが、一般的な質問は見つかりませんでした。


Angular 2アプリの最適化の詳細については、こちらをご覧
Timathon

1
しかし、私は、angular-cliが進化し、物事がどんどん良くなることを気にする必要はないと思います。angular-cliにない機能が必要な場合は、リポジトリの問題を提出してください:github.com/angular/angular-cli
Timathon

@Timathonはいくつかの点で正しいと思いますが、Angular2を本番環境にデプロイしようとしている場合は、アプリのパフォーマンスに直接影響するバンドルサイズに注意する必要があります。角度パフォーマンスチェックリストは、何を改善できるかを確認するための優れたリソースです。角度のあるチームは、バンドルサイズの縮小に取り組んでいます。それがどこに行くのか見て興奮しました!
Jack Clancy

回答:


72

2020年2月の更新

この回答は非常に魅力的だったので、新しいAngular最適化で更新するのが最善だと思いました。

  1. 別の回答者が言ったように、 ng build --prod --build-optimizer Angular v5未満を使用している人々にとっては良いオプションです。新しいバージョンでは、これはデフォルトでng build --prod
  2. 別のオプションは、アプリケーションをより小さなチャンクに分割するために、モジュールチャンク/レイジーロードを使用することです
  3. Angular 9にはIvyレンダリングエンジンがデフォルトで付属しており、バンドルサイズが改善されています
  4. サードパーティの開発者がツリーを揺らすことができることを確認してください。Rxjs v6をまだ使用していない場合は、使用する必要があります。
  5. 他のすべてが失敗した場合は、webpack-bundle-analyzerなどのツールを使用して、モジュールの膨張の原因を調べます
  6. ファイルがgzip圧縮されているかどうかを確認する

AOTコンパイルを使用すると、ベンダーバンドルのサイズを250kbに減らすことができると主張する人もいます。ただし、BlackHoleGalaxyの例では、AOTコンパイルを使用しng build --prod --aot、想定される250kbより10倍大きい2.7メガバイトのベンダーバンドルサイズが残っています。これは、たとえv4.0を使用している場合でも、angular2アプリケーションでは通常のことです。2.75MBは、特にモバイルデバイスでパフォーマンスを重視する人にとってはまだ大きすぎます。

アプリケーションのパフォーマンスを向上させるためにできることがいくつかあります。

1)AOT&Tree Shaking(angular-cliは箱から出してこれを行います)。Angular 9では、AOTはデフォルトで製品および開発環境にあります。

2)Angular Universal AKAサーバー側レンダリングの使用(CLIではない)

3)Webワーカー(ここでも、CLIではありませんが、非常に要求されている機能です)を
参照してください:https : //github.com/angular/angular-cli/issues/2305

4)サービスワーカー
は次を参照してください:https : //github.com/angular/angular-cli/issues/4006

これらすべてを1つのアプリケーションで必要とするわけではありませんが、Angularのパフォーマンスを最適化するために現在存在するオプションの一部です。私は、Googleがパフォーマンスの点ですぐに使える欠点を認識しており、将来的にこれを改善する計画を持っていることを望んでいます。

ここに、私が上で述べたいくつかの概念についてより深く話すリファレンスがあります:

https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294


私の最小限のプロジェクトは、参照384kBなんてあるgithub.com/JCornat/min-angular私は確かにそれを最適化する簡単な方法があるが、それは250KBに近いです!
ジャックコルナット2017年

2
@JacquesCornatよさそうです!ただし、アプリには単一のコンポーネントしかありません。問題は、バンドルサイズまたはより大きなアプリケーションを管理する方法です。多くの場合、AOTはバンドルサイズを十分に縮小せず、人々は他の方法で最適化することを余儀なくされます。皆さんにwebpack-bundle-analyzerをチェックすることを強くお勧めします。何が膨らみを引き起こしているのかを確認するのに非常に役立つ/簡単な方法
Jack Clancy

残念ながら、このようなユーティリティsw-precacheは2MBを超えるベンダーバンドルの処理を拒否します。

1
@JackClancy「問題は、バンドルサイズまたはより大きなアプリケーションを管理する方法です。」彼の質問は、「このバンドルサイズを改善する方法は?」です。彼は、3つのコンポーネントを備えた最小限のアプリについて話している。とにかく、AngularClass / angular-starter構成を使用して大きなバンドルについて話すと、私のリポジトリと同じように、大きなアプリのバンドルサイズは8MB(マップファイルなしで4MB)から580kBになりました。
ジャックコルナット2017

1
ありがとう、あなたは私を救った。--prodはアプリのサイズを6Mbから1.2Mbに縮小しました。まだ完璧ではありませんが、デスクトップでの使用のみを目的として受け入れています。
Vyacheslav Tsivina

21

最新のangular cliバージョンを使用し、コマンドng build --prod --build-optimizerを使用します。 これにより、prod envのビルドサイズが確実に縮小されます。

これは、ビルドオプティマイザが内部で行うことです。

ビルドオプティマイザーには2つの主要なジョブがあります。最初に、アプリケーションの一部を純粋としてマークできます。これにより、既存のツールによって提供されるツリーの揺れが改善され、アプリケーションの不要な部分が削除されます。

ビルドオプティマイザーが行う2つ目のことは、アプリケーションのランタイムコードからAngularデコレーターを削除することです。デコレーターはコンパイラーによって使用され、実行時に必要とされず、削除することができます。これらの各ジョブにより、JavaScriptバンドルのサイズが減少し、ユーザーのアプリケーションの起動速度が向上します。

:Angular 5以降の1つのアップデートでng build --prod、上記のプロセスを自動的に処理します:)


1
現在、angular 6に関しては、ベンダーは、angular / materialと
firebaseを

それは角度/材料の問題ですが、私はそのエラーに直面しました。ツリーの揺れが正しく行われていないことが、おそらく根本的な原因です。新しいレンダラーエンジンIVYでおそらく解決されるでしょう。
Shubhendu Vaid

13

Lodashは、バンドルからのインポート方法に応じて、コードのバグチャンクをバンドルに提供できます。例えば:

// includes the entire package (very large)
import * as _ from 'lodash';

// depending on your buildchain, may still include the entire package
import { flatten } from 'lodash';

// imports only the code needed for `flatten`
import flatten from 'lodash-es/flatten'

個人的に、私はユーティリティ関数からより小さなフットプリントを望んでいました。たとえば、最小化した後、バンドルflattenまで貢献でき1.2Kます。だから私は単純化されたlodash関数のコレクションを構築しています。の私の実装は、flatten周りに貢献してい50 bytesます。あなたがそれがあなたのために働くかどうか見るためにここでそれをチェックすることができます:https : //github.com/simontonsoftware/micro-dash


1
2 /上記のコメントから「loadash-es」のヒントを試しました。それは私のバンドルサイズを0.08mbに縮小します。
Stefdelec

それは多くありません!古い方法でlodashをインポートする他に何かありますか?すべてが新しい方法でインポートされない限り、ヘルプは得られません。
エリックサイモントン2018

すべてを交換したと思います。それ以外の場合、サイズは変更されません。以下に別のヒント(gzipについて)を示しました。
Stefdelec、2018

面白い。あなたのバンドルのどれくらいがlodashに貢献していますか/貢献しましたか?(例:を使用source-map-explorer
Eric Simonton 2018

11

まず、Angular 2は多くのライブラリに依存しているため、ベンダーバンドルは巨大です。Angular 2アプリの最小サイズは約500KB(場合によっては250KB、下の投稿を参照)です。
ツリーの揺れは、によって適切に使用されangular-cliます。デバッグのみに使用されるため、ファイルを含めないで
ください。さらに、ホット交換モジュールを使用している場合は、それを取り外してベンダーを軽くします。.map

本番用にパックするには、Webpackを個人的に使用します(そして、angular-cliもそれに依存します)。これはconfigure everything、最適化やデバッグを実際に行うことができるためです。
を使用したい場合Webpackは、最初の表示が少しトリッキーであることに同意しますが、ネット上のチュートリアルを参照してください。がっかりすることはありません。
それ以外の場合はangular-cli、を使用してください。

アプリを最適化し、Angular 2アプリを250KBに縮小するには、事前コンパイルを使用することが必須です

これが、最小のAngularバンドルサイズをテストするために作成したリポジトリ(github.com/JCornat/min-angular)で、384kBを取得しています。私はそれを最適化する簡単な方法があると確信しています。

上記のリポと同じように、AngularClass / angular-starter構成を使用して大きなアプリについて話すと、大きなアプリ(150以上のコンポーネント)のバンドルサイズは8MB(マップファイルなしで4MB)から580kBになりました


バンドルサイズの削減に役立つ具体的な角度スターター構成は何ですか?それはwebpack.configですか?
MartinJH

2
はい、バンドルサイズを縮小するのはwebpack構成です。
Jacques Cornat

説明をありがとう:)
MartinJH

8

次のソリューションは、nodejsを使用してdist /フォルダーを提供していることを前提としています。ルートレベルで次のapp.jsを使用してください

const express = require('express'),http = require('http'),path = require('path'),compression = require('compression');

const app = express();

app.use(express.static(path.join(__dirname, 'dist')));
app.use(compression()) //compressing dist folder 
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
})

const port = process.env.PORT || '4201';
app.set('port', port);

const server = http.createServer(app);
server.listen(port, () => console.log('Running at port ' + port))

必ず依存関係をインストールしてください。

npm install compression --save
npm install express --save;

次にアプリをビルドします

ng build --prod --build-optimizer

ビルドをさらに圧縮したい場合は、から300kb(約)を減らして、以下のプロセスに従ってください。

フォルダを作成vendorsrcのフォルダおよび内部のベンダーファイルを作成したフォルダrxjs.ts と、その中に以下のコードを貼り付けを。

export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';

そしてtsconfig.json、あなたのangular-cliアプリケーションのファイルに以下を追加します。次にcompilerOptions、次のjsonを追加します。

"paths": {
      "rxjs": [
        "./vendor/rxjs.ts"
      ]
    }

これにより、ビルドサイズが小さくなりすぎます。私のプロジェクトでは、サイズを11MBから1MBに縮小しました。それが役に立てば幸い


5

共有したいことの1つは、インポートされたライブラリがどのようにdistのサイズを増やすかです。angular2-momentパッケージをインポートしましたが、@ angular / commonからエクスポートされた標準のDatePipeを使用して、必要なすべての日時フォーマットを実行できました。

Angular2-モーメント "angular2-moment": "^1.6.0",

チャンク{0} polyfills.036982dc15bb5fc67cb8.bundle.js(ポリフィル)191 kB {4} [初期] [レンダリング]チャンク{1} main.e7496551a26816427b68.bundle.js(メイン)2.2 MB {3} [初期] [レンダリング]チャンク{2} styles.056656ed596d26ba0192.bundle.css(styles)69バイト{4} [初期] [レンダリング]チャンク{3} vendor.62c2cfe0ca794a5006d1.bundle.js(ベンダー)3.84 MB [初期] [レンダリング]チャンク{4 } inline.0b9c3de53405d705e757.bundle.js(インライン)0バイト[エントリ] [レンダリング]

Angular2モーメントを削除し、代わりにDatePipeを使用した後

チャンク{0} polyfills.036982dc15bb5fc67cb8.bundle.js(ポリフィル)191 kB {4} [初期] [レンダリング]チャンク{1} main.f2b62721788695a4655c.bundle.js(メイン)2.2 MB {3} [初期] [レンダリング]チャンク{2} styles.056656ed596d26ba0192.bundle.css(styles)69バイト{4} [初期] [レンダリング]チャンク{3} vendor.e1de06303258c58c9d01.bundle.js(ベンダー)3.35 MB [初期] [レンダリング]チャンク{4 } inline.3ae24861b3637391ba70.bundle.js(インライン)0バイト[エントリ] [レンダリング]

ベンダーバンドルが半分のメガバイトを削減したことに注意してください

重要なのは、外部ライブラリに慣れている場合でも、角度の標準パッケージが何を実行できるかを確認する価値があるということです。



1

実行した場合ng build --prod- vendorファイルはまったくないはずです。

単に実行した場合ng build-私はこれらのファイルを取得します:

ここに画像の説明を入力してください

フォルダの合計サイズは約14MBです。わあ!:D

しかし、実行するとng build --prod-これらのファイルを取得します。

ここに画像の説明を入力してください

フォルダの合計サイズは584Kです。

1つの同じコード。どちらの場合もIvyを有効にしました。角度は8.2.13です。

だから-私はあなたが--prodあなたのビルドコマンドに追加しなかったと思いますか?


1

Angular 8+を使用していて、バンドルのサイズを小さくしたい場合は、Ivyを使用できます。IvyはAngular 9のデフォルトのビューエンジンとして提供されています。src/ tsconfig.app.jsonに移動して、angularCompilerOptionsパラメーターを追加するだけです。次に例を示します。

{
  "extends": ...,
  "compilerOptions":...,
  "exclude": ...,

/* add this one */ 
  "angularCompilerOptions": {
    "enableIvy": true
  }
}

1

これは私の場合サイズを減らしました:

ng build --prod --build-optimizer --optimization.

Angular 5+の場合、ng-build --prodはデフォルトでこれを行います。このコマンドを実行した後のサイズは1.7MBから1.2MBに減少しましたが、私の実稼働目的には十分ではありません。

私はFacebookのメッセンジャープラットフォームで作業しており、メッセンジャーアプリをメッセンジャープラットフォームで実行するには1MB未満である必要があります。効果的な木の揺れのための解決策を理解しようとしていましたが、まだ運がありません。


1

その作品100%ng build --prod --aot --build-optimizer --vendor-chunk = true


0

私は角張った5 +スプリングブートアプリ(application.properties 1.3+)を使用しており、圧縮(以下のリンクを添付)を使用してmain.bundle.tsのサイズを2.7 MBから530 KBに減らすことができました。

また、デフォルトでは--aotと--build-optimizerが--prodモードで有効になっているため、これらを個別に指定する必要はありません。

https://stackoverflow.com/a/28216983/9491345


0

ng build --configuration = productionの省略形であるため、ng build --prodの「production」という名前の構成があることを確認してください。 問題は画面の真正面にあったので、答えは私の問題を解決しませんでした。これはかなり一般的なことだと思います... i18nを使用してアプリを国際化し、すべての構成の名前を、たとえばproduction-enに変更しました。次に、デフォルトの最適化が使用され、最適に近いはずであると想定して、ng build --prodでビルドしましたが、実際にはng buildのみが実行され、250kbではなく7mbバンドルが生成されました。


0

angular docs v9(https://angular.io/guide/workspace-config#alternate-build-configurations)から取得:

デフォルトでは、本番設定が定義されており、ng buildコマンドには、この設定を使用してビルドする--prodオプションがあります。プロダクション構成は、ファイルのバンドル余計な空白の最小化コメントとデッドコードの削除、短くて不可解な名前を使用するようにコードを書き換えるなどのさまざまな方法でアプリを最適化するデフォルトを設定します(「縮小」)。

さらに、@ angular-builders / custom-webpack:browserビルダーを使用してすべてのデプロイ可能ファイルを圧縮できます。ここで、カスタムwebpack.config.jsは次のようになります。

module.exports = {
  entry: {
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash].js'
  },
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: true,
    })
  ]
};

その後、圧縮されたコンテンツを提供するようにWebサーバーを構成する必要があります。例えば、nginxを使用して、nginx.confに追加する必要があります。

server {
    gzip on;
    gzip_types      text/plain application/xml;
    gzip_proxied    no-cache no-store private expired auth;
    gzip_min_length 1000;
    ...
}

私の場合、ngビルドで--prodを使用した直後にdistフォルダーが25 mbから5 mbに縮小し、圧縮後にさらに1.5 mbに縮小しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.