如何提高Angular2应用程序的加载性能?

Ang*_*arM 52 javascript performance systemjs angular2-routing angular

Angular2应用程序加载缓慢,如何提高负载性能?

我使用Angular2,打字稿和html5.

目前我的应用需要4秒才能加载.我使用Firebase托管并使用cloudflare.

我正在做的事情/信息:

  • 我压缩了图像.
  • 我缩小了CSS
  • 我缩小了js.
  • 我在脚本上使用async.
  • 我的脚本在我的.
  • 脚本大约700kb
  • 我使用谷歌速度测试获得65%
  • 我使用了libs的缩小版本,例如bootstrap等.
  • 使用systemjs.
  • 这是使用的种子应用程序:https://github.com/mgechev/angular-seed

流:

当应用程序加载时,它会显示一个蓝屏(这是bootstrap css),然后4秒后应用程序加载并且工作得非常快.但需要4秒钟才能加载.似乎systemjs缩小的app.js文件正在减慢整个应用程序,并且没有足够快地显示视图.

这是我的网站速度测试: https ://www.webpagetest.org/result/161206_F5_N87/

这是我的网站:

https://thepoolcover.co.uk/

如果您需要有关我的应用程序的更多信息以及我可以执行的任何其他操作,请告诉我.

Vik*_*iya 111

单个页面应用程序通常在加载时需要更多时间,因为它一次加载所有必需的东西.

我也面临同样的问题,我的团队通过使用以下方法优化了我们的项目,从8秒加载到2秒.

  1. 延迟加载模块: 延迟加载模块有助于减少启动时间.使用延迟加载,我们的应用程序不需要一次加载所有内容,它只需要加载用户在应用程序首次加载时期望看到的内容.只有在用户导航到其路线时才会加载延迟加载的模块.Angular2在其最终版本RC5中引入了模块.请参阅下面的分步指南.

  2. Aot编译: 使用AoT,浏览器下载应用程序的预编译版本.浏览器加载可执行代码,以便它可以立即呈现应用程序,而无需先等待编译应用程序.

    它减少了有效负载大小:如果应用程序已经编译,则无需下载Angular编译器.编译器大约是Angular本身的一半,因此省略它会大大降低应用程序的有效负载.欲了解更多信息请参阅.

  3. Webpack: Webpack是一种流行的模块捆绑器,它是一种工具,用于将应用程序源代码捆绑在方便的块中,并将该代码从服务器加载到浏览器中.您可以使用webpack配置Angular 2 Web应用程序(请参阅本指南).

  4. 从index.html中删除脚本,样式表:删除index.html中不需要的所有脚本和样式表.您可以通过调用服务在组件本身中动态加载这些脚本.

    创建一个文件script.service.ts,可以根据需要加载该组件的任何脚本

\ script.service.ts

import { Injectable } from '@angular/core';
declare var document: any;

@Injectable()
export class Script {

  loadScript(path: string) {
    //load script
    return new Promise((resolve, reject) => {
      let script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = path;
      if (script.readyState) {  //IE
        script.onreadystatechange = () => {
          if (script.readyState === "loaded" || script.readyState === "complete") {
            script.onreadystatechange = null;
            resolve({ loaded: true, status: 'Loaded' });
          }
        };
      } else {  //Others
          script.onload = () => {
            resolve({ loaded: true, status: 'Loaded' });
          };
      };
      script.onerror = (error: any) => resolve({ loaded: false, status: 'Loaded' });
      document.getElementsByTagName('head')[0].appendChild(script);
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

这只是动态加载脚本的示例代码,您可以根据需要自行定制和优化脚本.对于样式表,您应该使用styleUrl将其加载到组件中.

  1. 使用浏览器缓存:使用浏览器缓存时,您的网页文件将存储在浏览器缓存中.对于重复访问者,您的页面加载速度会快得多,共享相同资源的其他页面也会加载.有关详细信息,请访问https://varvy.com/pagespeed/leverage-browser-caching.html

  2. 最小化app.component.ts中的代码:最小化app.component.ts中存在的代码,该代码在应用程序加载或重新加载时始终运行.

  3. 在app上设置数据初始化:如果你在项目或组件中多次使用相同的api调用,或者你依赖于多个组件中的相同数据,而不是多次调用api,你可以将数据保存为对象在应用程序初始化的服务.该服务将在整个项目中充当单例,您可以在不调用api的情况下访问该数据.


延迟加载模块一步一步

  1. 模块化结构:我们必须将我们的应用程序划分为单独的模块.例如,一个应用程序可能有一个用户端和一个管理员端,每个应用程序都有自己不同的组件和路由,因此我们将这两个侧面分为admin.module.ts和user.module.ts模块.

  2. 根模块:每个Angular应用程序都有一个根模块类.按照惯例,它是一个名为app.module.ts的文件中名为AppModule的类,该模块将导入上述两个模块以及AppComponent以进行引导.您还可以根据需要声明多个组件.app.module.ts中的示例代码:

\ app.module.ts

import { NgModule } from '@angular/core';
import { UserModule } from './user/user.module';
import { AdminModule } from './admin/admin.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login.component';

@NgModule({
  imports: [UserModule, AdminModule],
  declarations: [AppComponent, LoginComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)
  1. 路线: 现在在您的路线中,您可以指定如下

\ app.router.ts

import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './login.component';

const routes: Routes = [
  { path: 'login', component: 'LoginComponent' }, //eager loaded
  { path: 'admin', loadChildren: './admin/admin.module#AdminModule' }, // Lazy loaded module
  { path: 'user', loadChildren: './user/user.module#UserModule' }  //lazy loaded module
];
Run Code Online (Sandbox Code Playgroud)

现在,当应用程序加载时,它只会加载LoginComponent和AppComponent代码.只有在访问/ admin或/ user路由时才会加载这些模块.因此,它将减少用于加载到浏览器中的有效载荷的大小,从而导致快速加载.

  1. 嵌套模块:就像app.module一样,每个模块都有自己的一组组件和路由.随着项目变得越来越大,模块内部模块的嵌套是优化的最佳方式,因为我们可以在需要时懒洋洋地加载这些模块.

请注意

以上代码仅供参考,请参阅完整示例 https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html


Tim*_*zio 8

如何"代码分裂".

从Webpack站点:

"对于大型网络应用程序,将所有代码放入单个文件并不高效,特别是如果在某些情况下只需要某些代码块.Webpack有一个功能可以将您的代码库拆分为按需加载的"块".其他一些捆绑包称它们为"层","汇总"或"片段".此功能称为"代码分割".

链接在这里:

https://webpack.github.io/docs/code-splitting.html

请注意,Angular CLI使用Webpack.

此外,如果您的应用程序使用数据调用进行引导,请确保您没有阻止等待这些调用返回的组件的呈现.承诺,异步等


bra*_*ndo 5

如果不亲自操作整个代码库和后端,就很难诊断出你遇到的确切问题(正如其他人所说,问题可能根本没有角度).

话虽如此,我强烈建议你开始使用angular-cli.它由角度团队设计,可以在易于使用的命令行界面中完成您需要完成的所有操作.所以我的答案取决于使用angular-cli.

以下是优化ng2项目进行生产的一般事项:

1)提前(AoT)编译 - 捆绑/缩小/树木摇晃

看,忘记配置一堆gulp任务来完成所有这些事情的头痛.angular-cli只需一个简单的步骤即可处理Bundling/Minification/Tree-shaking/AOT编译:

ng build -prod -aot

这将在"dist"文件夹中生成以下js文件:

inline.d41d8cd98f00b204e980.bundle.js
vendor.d41d8cd98f00b204e980.bundle.js
main.d41d8cd98f00b204e980.bundle.js
styles.4cec2bc5d44c66b4929ab2bb9c4d8efa.bundle.css
Run Code Online (Sandbox Code Playgroud)
您还将获得这些文件的gzip压缩版本以进行更多优化:

inline.d41d8cd98f00b204e980.bundle.js.gz
vendor.d41d8cd98f00b204e980.bundle.js.gz
main.d41d8cd98f00b204e980.bundle.js.gz
Run Code Online (Sandbox Code Playgroud)

Angular的AOT编译将自动对您的代码进行"树摇动",并删除任何未使用的引用.例如,您可以在项目中使用lodash,但您可能只使用了一些lodash函数; 树摇晃将修剪掉你最后建造中不需要的所有未使用过的lodash部分.最重要的是,AOT编译将预编译您的所有代码和视图,这意味着浏览器需要很长时间才能使ng2应用程序滚动. 点击此处了解有关角度AOT编译的更多信息.

2)延迟加载应用程序的部分 如果您进一步将应用程序划分为不同的部分,则无需在应用程序首次加载时加载每个部分.您可以为应用程序指定不同的模块,然后可以将它们(通过angular-cli aot编译器)捆绑到不同的块中.在这里阅读以了解如何将项目组织成模块,您可以编译成只需要加载的卡盘.Angular-cli将为您管理这些块的创建.

3)Angular Universal 现在如果你真的想让你的加载时间非常快,那么你会想要考虑实现Angular Universal,这是在编译服务器上的初始视图时.我没有使用Angular Universal,因为我已经能够通过步骤1和2实现快速加载时间.但它在ng2工具集中是一个令人兴奋的选项.请记住,您不在服务器上编译或运行ng2应用程序,编译初始视图服务器端,以便用户快速收到一个html,因此用户感知加载时间非常快(即使满载仍然会落后一点).该步骤不排除对其他步骤的需要.作为奖励,Angular Universal也应该帮助SEO.

4)二次捆绑

如果我没有使用延迟加载,我通常会继续捆绑从AOT编译生成的分发文件.因此,我创建了一个main.bundle.js文件,该文件汇编了inline.js,vendor.js和main.js文件.我用gulp这个.

  • @shusson angular-cli 很好地支持 **AOT 和延迟加载**。唯一不起作用的是,如果您有自定义装饰器(例如使用 @ngrx/effects 时)。确实,海关装饰师被剥离了...... (2认同)