Angular2加载的文件请求过多

我正在使用Angular2制作一个网站,而且我有我想要的是一个问题。 在我的angular度页面的第一次加载时, SystemJS发出超过500个请求来检索angular2/src目录中的每个Angular2文件。 总的来说,首次下载量超过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文件的截图: 在这里输入图像说明

在这里输入图像说明

有没有办法避免所有这些要求?

我有完全相同的问题,实际上是看这个post的答案。 这是我为解决问题所做的。

  1. 修改您的项目使用webpack。 按照这个简短的教程: Angular2快速启动SystemJS到Webpack
  2. 这个方法会给你一个单一的JavaScript文件,但它是相当大的(我的项目文件超过5MB),需要被缩小。 为此,我安装了webpack globaly: npm install webpack -g 。 安装完成后,从您的应用程序根目录运行webpack -p 。 这使我的文件大小降低到大约700KB

从20秒和350个请求到3秒和7个请求。

我看你已经有了回应,这当然是好事。 但对于那些想要使用systemjs的人 (就像我也这样做),而不是去webpack,你仍然可以捆绑文件。 但是,它确实涉及到使用另一个工具(我使用gulp)。 所以…你将有以下systemjsconfiguration(不是在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中,你可以像这样构build一个bundle(使用来自system.config.jstsconfig.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在我的'ts' ts'gulp任务中使用:

 { "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秒钟的4mb …到了20个请求,在1.6秒(本地开发机器)中1.4MB。 但是在1.6秒内这些20个请求〜1.4mb还包含了一些其他的js和css,pipe理主题附带了一些在第一次加载时需要的html模板,我更喜欢使用外部模板templateUrl:'',而不是内联的,写在我的component.ts文件中。 当然,对于拥有数百万用户的应用来说,这还不够。 也应该实现初始加载和caching系统的服务器端渲染,我实际上设法做到这一点angular度普遍,但在Angular2testing版(花费大约200-240毫秒来加载相同的pipe理应用程序,以上需要1.6秒 – 我知道: 哇! )。 现在Angular2 RC出来了,但是我相信那些普遍使用的人会很快加快速度,特别是在ng-conf出现之后。 此外,他们还计划为PHP,ASP和其他一些应用程序制作Angular Universal,现在只能用于Nodejs。

编辑:其实,我刚刚发现,NG-CONF他们说,Angular Universal已经支持ASP(但它不支持Angular2> beta.15 :))…但让我们给他们一些时间,RC刚刚几天前

我认为你的问题与这个问题有关:

  • 我的angular2应用程序需要很长时间才能加载第一次用户,我需要帮助加快

为了准备好生产(并加快速度),你需要打包。

我的意思是将所有文件转换成JavaScript文件,然后像Angular2一样将它们连接起来。 这样你将有几个模块包含在一个JS文件中。 这样您将减lessHTTP调用的数量,以将您的应用程序代码加载到浏览器中。

我find了一个简单的解决scheme,在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. build立你的项目。
  2. 运行: npm run build_prod它将在public \ dist目录下创buildbundle.js&bundle.min.js。
  3. 编辑你的index.html文件:不要运行System.import('YourMainModule')... ,添加<script src="/dist/bundle.min.js"></script>

在angular度页面的第一次加载时,systemjs发出超过500个请求来检索angular2 / src目录中的每个angular2文件。 总共第一次下载量超过4MB,启动时间超过14s。

SystemJs工作stream程是相当新的,没有足够的研究,在最好的部署。

build议回到commonjs + webpack 。 更多: https : //basarat.gitbooks.io/typescript/content/docs/quick/browser.html

这里是一个例子: https : //github.com/AngularClass/angular2-webpack-starter

@ 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>

如果你想坚持SystemJS,你可以将你的应用程序与JSPM捆绑在一起。 到目前为止,我已经取得了很好的成功,使用JSPM的bundle-sfx命令为Angular 2应用程序创build单个JS文件。

这个Gist有一些有用的信息,还有一个种子项目。

我正在使用AG2 RC版本当使用MrCroft的解决scheme与systemjs-builder时,我遇到了很多问题,如:错误TS2304:找不到名称'地图'错误TS2304:找不到'承诺'的名字…

经过多次尝试,我添加了: ///<reference path="../../typings/index.d.ts" />到我的boot.ts,现在我得到了我的包文件编译。

Angular命令行界面现在支持捆绑(通过树状结构去除导入中未使用的代码),缩小和提前模板编译,这不仅极大地减less了请求的数量,而且还使捆绑非常小。 它在下面使用WebPack。

用它生产生产是非常容易的:

 ng build --prod --aot 

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