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 ответов:
у меня была точно такая же проблема, на самом деле смотрел на этот пост для ответа. Вот что я сделал, чтобы решить проблему.
- измените свой проект, чтобы использовать webpack. Следуйте этому короткому руководству: Angular2 QuickStart SystemJS To Webpack
- этот метод даст вам один файл 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" } }
- создайте свой проект.
- Run:npm run build_prod Это создаст пакет.js & bundle.минута.js в каталоге public\dist.
- редактировать : Вместо
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