web-dev-qa-db-ja.com

読み込み時にAngular2のファイルリクエストが多すぎます

Angular2を使用してWebサイトを作成していますが、問題だと思われるものがあります。 my angularページの最初のロードで、SystemJSAngular2ディレクトリ内のすべてのangular2/srcファイルを取得するために5億件以上のリクエストを行っています。 、最初のロードで4MB以上ダウンロードされ、開始に14秒以上かかります。

私のindex.htmlは以下のスクリプトを含みます:

<script src="libs/angular2/bundles/angular2-polyfills.js"></script>
<script src="libs/systemjs/dist/system.src.js"></script>
<script src="libs/rxjs/bundles/Rx.js"></script>
<script src="libs/angular2/bundles/angular2.min.js"></script>
<script src="libs/angular2/bundles/http.dev.js"></script>
<script src="libs/jquery/jquery.js"></script>
<script src="libs/lodash/lodash.js"></script>
<script src="libs/bootstrap/js/bootstrap.js"></script>

そして、私のsystemJs初期化コードは次のようになります。

    <script>
      System.config({
        defaultJSExtensions: true,
        paths: {
          '*': 'libs/*',
          'app/*': 'app/*'
        },
        packageConfigPaths: ['libs/*/package.json'],
        packages: {
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));

    </script>

パブリックフォルダーの構造は次のとおりです。

.
├── img
├── styles
├── app
├── libs
|   └── angular2
|   └── systemjs
|   └── rxjs
|   └── jquery
|   └── lodash
|   └── bootstrap
└── index.html

要求されているjsファイルのいくつかのスクリーンショット: enter image description here

enter image description here

これらのリクエストをすべて回避する方法はありますか?

57
Marcos Basualdo

私はまったく同じ問題を抱えていて、実際にこの投稿で答えを探していました。これが私が問題を解決するためにしたことです。

  1. Webpackを使用するようにプロジェクトを変更します。この短いチュートリアルに従ってください: Angular2 QuickStart SystemJS To Webpack
  2. このメソッドは単一のjavascriptファイルを提供しますが、非常に大きく(プロジェクトファイルは5MBを超えていた)、縮小する必要があります。これを行うには、webpack globaly:npm install webpack -g。インストールしたら、webpack -pアプリのルートディレクトリから。これにより、ファイルサイズが約700 KBになりました

20秒と350リクエストから3秒と7リクエストまで。

47
David Herod

すでに回答がありますが、それはもちろん良いことです。しかし、systemjs(私もそうです)を使用し、webpackに移動したくない場合は、ファイルをバンドルできます。ただし、別のツールも使用する必要があります(gulpを使用します)。だから...次のsystemjs設定があります(htmlではなく、別のファイルにあります-「system.config.js」と呼びましょう):

(function(global) {

    // map tells the System loader where to look for things
    var map = {
        'app':                        'dist/app', // this is where your transpiled files live
        'rxjs':                       'node_modules/rxjs',
        'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api', // this is something new since angular2 rc.0, don't know what it does
        '@angular':                   'node_modules/@angular'
    };

    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app':                        { main: 'boot.js',  defaultExtension: 'js' },
        'rxjs':                       { defaultExtension: 'js' },
        'angular2-in-memory-web-api': { defaultExtension: 'js' }
    };

    var packageNames = [
        '@angular/common',
        '@angular/compiler',
        '@angular/core',
        '@angular/http',
        '@angular/platform-browser',
        '@angular/platform-browser-dynamic',
        //'@angular/router', // I still use "router-deprecated", haven't yet modified my code to use the new router that came with rc.0
        '@angular/router-deprecated',
        '@angular/http',
        '@angular/testing',
        '@angular/upgrade'
    ];

    // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
    packageNames.forEach(function(pkgName) {
        packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
    });

    var config = {
        map: map,
        packages: packages
    };

    // filterSystemConfig - index.html's chance to modify config before we register it.
    if (global.filterSystemConfig) { global.filterSystemConfig(config); }

    System.config(config);
})(this);

次に、gulpfile.jsで次のようなバンドルを作成します(system.config.jsおよびtsconfig.jsonファイルの情報を使用):

var gulp = require('gulp'),
    path = require('path'),
    Builder = require('systemjs-builder'),
    ts = require('gulp-TypeScript'),
    sourcemaps  = require('gulp-sourcemaps');

var tsProject = ts.createProject('tsconfig.json');

var appDev = 'dev/app'; // where your ts files are, whatever the folder structure in this folder, it will be recreated in the below 'dist/app' folder
var appProd = 'dist/app';

/** first transpile your ts files */
gulp.task('ts', () => {
    return gulp.src(appDev + '/**/*.ts')
        .pipe(sourcemaps.init({
            loadMaps: true
        }))
        .pipe(ts(tsProject))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(appProd));
});

/** then bundle */
gulp.task('bundle', function() {
    // optional constructor options
    // sets the baseURL and loads the configuration file
    var builder = new Builder('', 'dist/system.config.js');

    /*
       the parameters of the below buildStatic() method are:
           - your transcompiled application boot file (the one wich would contain the bootstrap(MyApp, [PROVIDERS]) function - in my case 'dist/app/boot.js'
           - the output (file into which it would output the bundled code)
           - options {}
    */
    return builder
        .buildStatic(appProd + '/boot.js', appProd + '/bundle.js', { minify: true, sourceMaps: true})
        .then(function() {
            console.log('Build complete');
        })
        .catch(function(err) {
            console.log('Build error');
            console.log(err);
        });
});

/** this runs the above in order. uses gulp4 */
gulp.task('build', gulp.series(['ts', 'bundle']));

そのため、「gulp build」を実行すると、必要なすべての「bundle.js」ファイルが取得されます。もちろん、このgulpバンドルタスクを機能させるには、さらにいくつかのパッケージが必要です。

npm install --save-dev github:gulpjs/gulp#4.0 gulp-TypeScript gulp-sourcemaps path systemjs-builder

また、tsconfig.jsonに"module":"commonjs"があることを確認してください。 'ts' gulpタスクで使用されるtsconfig.jsonは次のとおりです。

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "noImplicitAny": false
    },
    "exclude": [
        "node_modules",
        "typings/main",
        "typings/main.d.ts"
    ]
}

次に、htmlファイルにこれを含めるだけで済みます。

<!-- Polyfill(s) for older browsers -->
<script src="node_modules/es6-shim/es6-shim.min.js"></script>

<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="dist/app/bundle.js"></script>

そしてそれだけです...私は600リクエスト、約5秒で4 mbから取得しました... 20リクエスト、1.6秒で1.4 mb(ローカル開発マシン)になりました。しかし、1.6秒でこれらの20のリクエストには、管理テーマに付属する他のjsおよびcssに加えて、最初の読み込みで必要になるいくつかのhtmlテンプレートが含まれます。外部テンプレート-templateUrl: component.tsファイルに記述されたインラインのもの。確かに、何百万人ものユーザーがいるアプリの場合、これではまだ十分ではありません。また、初期ロードとキャッシュシステムのサーバー側レンダリングを実装する必要があります。実際にangularユニバーサルでそれを行うことができましたが、Angular2ベータ版では(200-240ミリ秒上記の同じ管理アプリの初期レンダリングを読み込むには1.6秒かかります-私は知っています:WOW!)。現在、Angular2 RCがリリースされて以来、互換性はありませんが、特にng-confが登場するので、ユニバーサルをやっている人はすぐにスピードアップするでしょう。さらに、彼らはまた、PHP向けのAngular Universal、ASPおよびその他いくつかを計画しています-現在はNodejs専用です。

編集:実際、NG-CONFではAngular UniversalはすでにASPをサポートしていると言いました(しかしAngular2> beta.15をサポートしていません:))...しかし、少し時間を与えましょう。RCは数日前に登場しました

33
MrCroft

あなたの質問はこれに関連すると思います:

本番用の準備を整える(そして高速化する)には、パッケージ化する必要があります。

つまり、すべてのファイルをJavaScriptファイルに変換し、たとえばAngular2と同じ方法で連結します。これにより、複数のモジュールが単一のJSファイルに含まれます。この方法により、HTTP呼び出しの数を減らして、アプリケーションコードをブラウザーにロードします。

3

mgechevのangular2-seedリポジトリ でbrowserifyとuglifyjsを使用して、簡単な解決策を見つけました

これが私のバージョンです。

pacakge.json:

_{
...
  "scripts": {
      "build_prod": "npm run clean && npm run browserify",
      "clean": "del /S/Q public\\dist",
      "browserify": "browserify -s main  public/YourMainModule.js > public/dist/bundle.js && npm run minify",
      "minify": "uglifyjs public/dist/bundle.js --screw-ie8 --compress --mangle --output public/dist/bundle.min.js"
    },
...
  "devDependencies": {
      "browserify": "^13.0.1",    
      "TypeScript": "^1.9.0-dev.20160625-1.0",
      "typings": "1.0.4",
      "uglifyjs": "^2.4.10"
    }
}
_
  1. プロジェクトをビルドします。
  2. 実行:npm run build_prodpublic\distディレクトリの下にbundle.jsおよびbundle.min.jsを作成します。
  3. _index.html_ファイルを編集します:System.import('YourMainModule')... ,を実行する代わりに_<script src="/dist/bundle.min.js"></script>_を追加します
3
FreeBird72

My angularページの最初のロードで、systemjsは、angular2/srcディレクトリ内のすべてのangle2ファイルを取得するために5億件以上のリクエストを行っています。合計で、最初のロードは4MB開始する14秒以上。

SystemJのワークフローはかなり新しく、最適な展開のための十分な調査がありません。

commonjs + webpackに戻ることをお勧めします。詳細: https://basarat.gitbooks.io/TypeScript/content/docs/quick/browser.html

以下に例を示します。 https://github.com/AngularClass/angular2-webpack-starter

1
basarat

@ FreeBird72あなたの答えは素晴らしいです。

SystemJSを開発に使用し、本番サーバーの速度を上げたい場合。これをチェックしてください。

注:使用するコンポーネントのみをインポートし、パッケージ全体からインポートしないでください。

例:ng2-bootstrapからModalを使用する場合。

import {MODAL_DIRECTIVES} from "ng2-bootstrap/components/modal";

の代わりに:

import {MODAL_DIRECTIVES} from "ng2-bootstrap/ng2-bootstrap";

これにより、ng2-bootstrap全体ではなくモーダルコンポーネントがインポートされます。

その後、@ FreeBird72の回答に従ってください

このpackage.jsonを追加します

{
  ...
  "scripts": {
    ...
    "prod": "npm run tsc && npm run browserify",
    "browserify": "browserify -s main  dist/main.js > dist/bundle.js && npm run minify",
    "minify": "uglifyjs dist/bundle.js --screw-ie8 --compress --mangle --output dist/bundle.min.js",
    ...
  },
  "devDependencies": {
    ...
    "browserify": "^13.0.1",    
    "uglifyjs": "^2.4.10",
    ...
  }
  ...
}

次に、npm run tscを開発時に、npm run prodを実稼働サーバー上で使用できます。また、index.htmlからSystem.import(....を削除し、<script src="/dist/bundle.min.js"></script>に変更します。

1
lthh89vt

SystemJSを使用したい場合は、アプリを [〜#〜] jspm [〜#〜] にバンドルできます。これまでのところ、JSPMのbundle-sfxコマンドは、Angular 2つのアプリ用の単一のJSファイルを作成します。

this Gist にはいくつかの有用な情報があり、 シードプロジェクト があります

0
Harry

Angularコマンドラインインターフェイスは、バンドルからのインポート(未使用のコードをインポートから取り除くツリーシェーキング)、ミニファイ、事前テンプレートのコンパイルをサポートするようになりました。リクエストが行われますが、バンドルも非常に小さくなります。

本番環境でのビルドは非常に簡単です。

ng build --prod --aot

https://github.com/angular/angular-cli

0
Harry

AG2 RCバージョンを使用していますsystemjs-builderでMrCroftのソリューションを使用しているときに、次のような多くの問題に遭遇しました:エラーTS2304:名前 'Map'が見つかりませんエラーTS2304:名前 'Promise'が見つかりません...

何度も試した後、私は追加しました:///<reference path="../../typings/index.d.ts" />をboot.tsに追加し、バンドルファイルをコンパイルしました。

0
Wong Kim Wah