Angular2 слишком много запросов файлов При загрузке


я делаю сайт с помощью Angular2 и у меня есть то, что я полагаю, является проблемой. При первой загрузке моей угловой страницы,SystemJS делает более 500 сотен запросов, чтобы получить каждый на . В общей сложности, первая загрузка загружает более 4 МБ, и это занимает более 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, которые запрашиваются:

есть ли способ избежать всех этих запросов?

9 57

9 ответов:

у меня была точно такая же проблема, на самом деле смотрел на этот пост для ответа. Вот что я сделал, чтобы решить проблему.

  1. измените свой проект, чтобы использовать webpack. Следуйте этому короткому руководству: Angular2 QuickStart SystemJS To Webpack
  2. этот метод даст вам один файл javascript, однако он довольно большой (мой файл проекта был более 5 Мб) и должен быть уменьшен. Для этого я установил webpack globaly:npm install webpack -g. После установки, запустите webpack -p из корневого каталога приложения. Это привело мой размер файла до около 700KB

от 20 секунд и 350 запросов до 3 секунд и 7 запросов.

Я вижу, у вас уже есть ответ, что хорошо, конечно. Но для тех, кто хочет использовать systemjs (как и я), а не идти в webpack, вы все равно можете связывать файлы. Однако это также связано с использованием другого инструмента (я использую gulp). Так... у вас будет следующая конфигурация systemjs (не в html, а в отдельном файле - назовем ее "system.конфиг.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 bundle:

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

кроме того, убедитесь, что в вашем tsconfig.json у вас есть "module":"commonjs". Вот мой tsconfig.json, который используется в my 'ts' задач глоток:

{
    "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 запросов, 4 МБ примерно за 5 секунд... до 20 запросов, 1,4 МБ за 1,6 секунды (локальная машина разработки). Но эти 20 запросов ~1.4 mb за 1.6 секунды также включают в себя некоторые другие js и css, что тема admin поставляется с несколькими шаблонами html, которые требуются при первой загрузке, я предпочитаю использовать внешние шаблоны - templateUrl: "вместо встроенных, написанных в моем компоненте.файл ТС. Конечно, для приложения, которое будет иметь миллионы пользователи, этого все равно будет недостаточно. Также должен быть реализован рендеринг на стороне сервера для начальной загрузки и кэш-системы, мне действительно удалось сделать это с помощью angular universal, но на Angular2 beta (взял около 200-240 МС чтобы загрузить начальный рендер того же приложения администратора, что выше занимает 1,6 секунды - я знаю:вау!). Теперь это несовместимо с Angular2 радиоуправляемый вышел, но я уверен, что ребята делают универсальные получите его в ближайшее время скорость, специально с НГ-конф подходит. Кроме того, они также планируют сделать Angular универсальным для PHP, ASP и нескольких других - прямо сейчас это только для Nodejs.

Edit: На самом деле, я только что узнал, что на NG-CONF они сказали, что Angular Universal уже поддерживает ASP (но он не поддерживает Angular2 > beta.15 :)) ... но давайте дадим им некоторое время, вертолет только что вышел несколько дней назад

Я думаю, что ваш вопрос связан с этим:

чтобы иметь что-то готовое к производству (и ускорить его), вам нужно упаковать его.

Я имею в виду транспилирование всех файлов в JavaScript и объединение их так же, как это делает, например, Angular2. Таким образом, вы будете иметь несколько модулей, содержащихся в одном файле JS. Таким образом, вы уменьшите количество HTTP-запросов для загрузки кода приложения в браузере.

Я нашел простое решение, используя browserify & uglifyjs на хранилище angular2-seed мгечева

вот моя версия:

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. Run:npm run build_prod Это создаст пакет.js & bundle.минута.js в каталоге public\dist.
  3. редактировать : Вместо System.import('YourMainModule')... , добавить <script src="/dist/bundle.min.js"></script>

при первой загрузке моей угловой страницы systemjs делает более 500 сотен запросов для извлечения каждого файла angular2 в каталоге angular2/src. В общей сложности первая загрузка загружает более 4 МБ, и для запуска требуется более 14 секунд.

рабочие процессы SystemJs довольно новые и не имеют достаточного количества исследований в них для лучшего развертывания.

предлагаю вернуться к commonjs + webpack. Больше : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html

вот пример:https://github.com/AngularClass/angular2-webpack-starter

@FreeBird72 ваш ответ является удивительным.

если вы хотите использовать SystemJS для разработки и ускорения рабочего сервера, как я делаю. Проверить это.

Примечание: только импортируйте компоненты, которые вы используете, не импортируйте из всего пакета.

например: если вы хотите использовать модальный из ng2-bootstrap.

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

вместо:

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

это будет импортировать модальный компонент вместо целого ng2-bootstrap

затем следуйте ответу от @FreeBird72

добавить этот пакет.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 на рабочем сервере Также удалите System.import(.... из своего индекса.HTML и изменить его на <script src="/dist/bundle.min.js"></script>

Если вы хотите придерживаться SystemJS, вы можете связать свое приложение с JSPM. Я имел хороший успех с этим до сих пор, используя JSPM bundle-sfx команда для создания одиночных файлов JS для угловых приложений 2.

есть полезная информация в в этом суть, и проект семя.

Я использую версию AG2 RC При использовании решения MrCroft с systemjs-builder я столкнулся с множеством проблем, таких как: ошибка TS2304: не удается найти имя 'Map' ошибка TS2304: не удается найти имя 'Promise'...

после многих попыток, я добавил: ///<reference path="../../typings/index.d.ts" /> в мой сапог.ts и теперь я получил свой файл пакета скомпилирован.

интерфейс командной строки Angular теперь поддерживает пакетирование (с встряхиванием дерева, чтобы удалить неиспользуемый код из импорта), минимизацию и компиляцию шаблонов заранее, что не только значительно минимизирует количество сделанных запросов, но и делает пакет очень маленьким. Он использует WebPack внизу.

Это невероятно легко сделать производство строит с ним:

ng build --prod --aot

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