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的答案。 这是我为解决问题所做的。
- 修改您的项目使用webpack。 按照这个简短的教程: Angular2快速启动SystemJS到Webpack
- 这个方法会给你一个单一的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.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在我的'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" } }
- build立你的项目。
- 运行: npm run build_prod它将在public \ dist目录下创buildbundle.js&bundle.min.js。
- 编辑你的
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