簡體   English   中英

Angular2加載的文件請求過多

[英]Angular2 too many file requests on load

我正在使用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文件的屏幕截圖: 在此處輸入圖片說明

在此處輸入圖片說明

有辦法避免所有這些請求嗎?

我有完全相同的問題,實際上是在看這篇文章的答案。 這是我為解決問題所做的工作。

  1. 修改您的項目以使用webpack。 請遵循以下簡短教程: Angular2 QuickStart SystemJS到Webpack
  2. 此方法將為您提供單個javascript文件,但是它很大(我的項目文件超過5MB),並且需要縮小。 為此,我全局安裝了webpack: npm install webpack -g 安裝后,從您的應用程序根目錄運行webpack -p 這使我的文件大小減小到約700KB

從20秒和350個請求降低到3秒和7個請求。

我看到您已經有回應,這當然很好。 但是對於那些想要使用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.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捆綁包任務正常工作:

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秒內的4mb)到20個請求(1.6秒內的1.4mb)(本地開發機器)。 但是這20個請求在1.6秒內達到約1.4mb,其中還包括管理主題附帶的其他js和CSS,以及一些首次加載時需要的html模板,我更喜歡使用外部模板-templateUrl:”,而不是內聯代碼,寫在我的component.ts文件中。 當然,對於擁有數百萬用戶的應用程序來說,這還遠遠不夠。 同樣應該為初始加載和緩存系統實現服務器端渲染,我實際上設法使用angular Universal做到了這一點,但是在Angular2 beta(花了大約200-240毫秒來加載同一個管理應用程序的初始渲染,而上述花費1.6秒-我知道: 哇! )。 自從Angular2 RC發布以來,它就已經不兼容了,但是我敢肯定,進行通用開發的人很快就會加快速度,特別是因為ng-conf即將推出。 此外,他們還計划將Angular Universal用於PHP,ASP和其他一些工具-現在僅適用於Node.js。

編輯:實際上,我剛剛發現他們在NG-CONF上說Angular Universal已經支持ASP(但是它不支持Angular2> beta.15:))...但是讓我們給他們一些時間,RC剛剛問世。幾天前

我認為您的問題與此有關:

要准備好某些東西以進行生產(並加快速度),您需要對其進行打包。

我的意思是將所有文件都轉換為JavaScript文件,然后像Angular2一樣將它們合並。 這樣,您將在單個JS文件中包含多個模塊。 這樣,您將減少將應用程序代碼加載到瀏覽器中的HTTP調用次數。

我找到了一個簡單的解決方案,在mgechev的angular2種子存儲庫上使用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_prod它將在public \\ dist目錄下創建bundle.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工作流是相當新的,並且沒有足夠的研究來最好地進行部署。

建議回到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應用制作了單個JS文件。

Gist中有一些有用的信息,並且有一個種子項目。

我正在使用AG2 RC版本在將MrCroft的解決方案與systemjs-builder一起使用時,我遇到了很多問題,例如:錯誤TS2304:找不到名稱“地圖”錯誤TS2304:找不到名稱“承諾” ...

經過多次嘗試,我在///<reference path="../../typings/index.d.ts" />添加了///<reference path="../../typings/index.d.ts" /> ,現在我的捆綁文件已編譯好。

Angular命令行界面現在支持捆綁(通過搖晃來從導入中刪除未使用的代碼),最小化和提前模板編譯,這不僅極大地減少了發出的請求數量,而且使捆綁非常小。 它在下面使用WebPack。

使用它進行生產構建非常容易:

ng build --prod --aot

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM