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

时间:2016-11-30 17:34:31

标签: javascript performance angular angular2-routing systemjs

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

我使用Angular2,打字稿和html5。

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

我正在做的事情/信息:

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

流量:

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

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

这是我的网站:

https://thepoolcover.co.uk/

如果您需要有关我的应用以及我可以执行的任何其他操作的更多信息,请与我们联系。

6 个答案:

答案 0 :(得分:111)

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

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

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

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

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

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

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

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

  5. \ 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);
        });
      }
    }
    

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

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

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

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

    4. 逐步加载模块

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

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

      3. \ 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 { }
        
        1. 路线:现在您的路线中可以指定如下
        2. \ 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
          ];
          

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

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

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

答案 1 :(得分:8)

&#34;代码拆分&#34;。

来自Webpack网站:

&#34;对于大型网络应用程序,将所有代码放入单个文件并不高效,尤其是在某些情况下仅需要某些代码块时。 Webpack具有将代码库拆分为按需加载的“块”的功能。其他一些捆绑包称它们为“层”,“汇总”或“碎片”。此功能称为“代码分割”。

链接到这里:

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

请注意,Angular CLI使用Webpack。

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

答案 2 :(得分:6)

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

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

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

1)提前(AoT)编辑 - 捆绑/缩小/树木震动

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

  

ng build -prod -aot

这将在你的&#34; dist&#34;中生成以下js文件文件夹:

&#13;
&#13;
inline.d41d8cd98f00b204e980.bundle.js
vendor.d41d8cd98f00b204e980.bundle.js
main.d41d8cd98f00b204e980.bundle.js
styles.4cec2bc5d44c66b4929ab2bb9c4d8efa.bundle.css
&#13;
&#13;
&#13; 您还将获得这些文件的gzip压缩版本以进行更多优化:

inline.d41d8cd98f00b204e980.bundle.js.gz
vendor.d41d8cd98f00b204e980.bundle.js.gz
main.d41d8cd98f00b204e980.bundle.js.gz

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

2)延迟加载应用的部分 如果您进一步将应用程序划分为不同的部分,则在首次加载应用程序时无需加载每个应用程序。您可以为应用程序指定不同的模块,然后可以将它们(通过angular-cli aot编译器)捆绑到不同的块中。阅读here以了解如何将项目组织成模块,您可以将这些模块编译成仅按需要加载的卡盘。 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这个。

答案 3 :(得分:2)

因为它的SPA和角度2 init太慢了。而已。加上RXjs,大量的polifill等.AOT可以提供帮助,但很多angular2 libs都无法使用它。角度普遍真正的帮助

答案 4 :(得分:0)

使用以下命令构建您的角度应用程序,以获得最大的优化收益。

ng build --prod --aot --optimization --build-optimizer --vendor-chunk --common-chunk --extract-licenses --extract-css --source-map=false

基本上,您将以aot模式进行构建,并使用树状结构进行一些优化。

  • 优化:启用对构建输出的优化。

  • vendor-chunk:使用仅包含供应商库的单独捆绑软件。

  • common-chunk:使用单独的捆绑软件,其中包含跨多个捆绑软件使用的代码。
  • extract-css:将全局样式的css提取到css文件中,而不是js文件中。
  • build-optimizer:使用'aot'选项时启用@ angular-devkit / build-optimizer优化。
  • source-map = false:删除源地图也会减小捆绑包的大小

答案 5 :(得分:-3)

尝试运行ng serve --sourcemap=false

来停用源地图