如何提高 Angular2 应用程序的加载性能?
How can I improve load performance of Angular2 apps?
Angular2 应用加载缓慢,如何提高加载性能?
我使用 Angular2,打字稿 html5。
目前我的应用程序需要 4 秒才能加载。
我使用 Firebase 托管并使用 cloudflare。
我正在做的事情/信息:
- 我压缩了图片。
- 我缩小css
- 我缩小js。
- 我在我的脚本上使用异步。
- 我的脚本在我的.
- 脚本大约 700kb
- 我使用 google 速度测试并获得 65%
- 我使用了我使用的库的缩小版本,例如bootstrap等
- 使用 systemjs。
- 这是我使用的种子应用程序:https://github.com/mgechev/angular-seed
流量:
应用程序加载时显示蓝屏(这是 bootstrap css),然后 4 秒后应用程序加载并运行得非常快。但加载需要 4 秒。似乎 systemjs 缩小到的 app.js 文件正在减慢整个应用程序,并且显示视图的速度不够快。
这是我的网站速度测试:
https://www.webpagetest.org/result/161206_F5_N87/
这是我的网站:
如果您需要有关我的应用程序以及我可以做的任何其他事情的更多信息,请告诉我。
"code splitting"怎么样。
来自 Webpack 站点:
“对于大型 Web 应用程序,将所有代码放入单个文件中效率不高,尤其是如果仅在某些情况下需要某些代码块。Webpack 具有将代码库拆分为加载的“块”的功能按需。其他一些打包器称它们为“层”、“汇总”或“片段”。此功能称为“代码拆分”。
Link 这里:
https://webpack.github.io/docs/code-splitting.html
请注意,Angular CLI 使用 Webpack。
此外,请确保如果您的应用通过数据调用进行引导,则您不会阻止等待这些调用 return 的组件的呈现。承诺、异步等
如果没有 hands-on 整个代码库和后端,很难诊断出您遇到的确切问题(正如其他人所建议的,问题可能根本不是 angular)。
话虽如此,我强烈建议您开始使用 angular-cli。它由 angular 团队设计,旨在完成您需要在 easy-to-use 命令行界面中完成的所有事情。所以我的回答是基于 angular-cli 的使用。
以下是您可以为生产环境优化 ng2 项目的一般操作:
1) 提前 (AoT) 编译 - Bundling/Minification/Tree-shaking
看,忘掉配置一堆 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
您还将获得这些文件的 gzip 版本以进行更多优化:
inline.d41d8cd98f00b204e980.bundle.js.gz
vendor.d41d8cd98f00b204e980.bundle.js.gz
main.d41d8cd98f00b204e980.bundle.js.gz
Angular 的 AOT 编译将自动对您的代码执行 "tree shaking" 并删除任何未使用的引用。例如,您可能在项目中使用了 lodash,但您可能只使用了几个 lodash 函数; tree shaking 将 trim 移除最终构建中不需要的 lodash 中所有未使用的部分。最重要的是,AOT 编译将 pre-compile 你所有的代码和视图,这意味着浏览器运行 ng2 应用所需的时间更少。 Click here 有关 angular 的 AOT 编译的更多信息。
2) 应用的延迟加载部分
如果您进一步将您的应用程序分成不同的部分,您不需要在您的应用程序首次加载时加载所有内容。您可以为您的应用程序指定不同的模块,然后可以将这些模块(由 angular-cli aot 编译器)捆绑到不同的块中。阅读 here 以了解如何将您的项目组织成模块,您可以将这些模块编译成仅在需要时加载的卡盘。 Angular-cli 将为您管理这些块的创建。
3) Angular 通用
现在,如果你真的想让你的加载时间非常快,那么你将要考虑实施 Angular Universal,这是在你在服务器上编译你的初始视图时。我没有使用 Angular Universal,因为我已经能够通过步骤 1 和 2 实现快速加载时间。但它是 ng2 工具集中的一个令人兴奋的选项。请记住,您没有在服务器上编译或 运行 ng2 应用程序,而是在服务器端编译初始视图,以便用户快速收到 html 的震动,因此用户认为加载时间是非常快(即使满载仍然会落后一点)。此步骤并不排除对其他步骤的需要。作为奖励,Angular Universal 也应该有助于 SEO。
4)二次捆绑
如果我不使用延迟加载,我通常会进一步捆绑AOT编译生成的分发文件。因此,我创建了一个 main.bundle.js 文件,其中包含 inline.js、vendor.js 和 main.js 文件。我为此使用 gulp。
单页应用程序通常在加载时需要更多时间,因为它一次加载所有必要的东西。
我也遇到过同样的问题,我的团队使用以下方法优化了我们的项目,从 8 秒加载到 2 秒。
延迟加载模块:延迟加载模块有助于减少启动时间。使用延迟加载,我们的应用程序不需要一次加载所有内容,它只需要加载用户希望在应用程序首次加载时看到的内容。延迟加载的模块只会在用户导航到他们的路线时加载。 Angular2 在其最终版本 RC5 中引入了模块。 请参阅下面的分步指南。
Aot 编译: 使用 AoT,浏览器会下载应用程序的预编译版本。浏览器加载可执行代码,以便它可以立即呈现应用程序,而无需先等待编译应用程序。
它减少了负载大小: 如果应用程序已经编译,则无需下载 Angular 编译器。编译器大约是 Angular 本身的一半,因此省略它会大大减少应用程序的负载。有关详细信息,请参阅 this。
Webpack : Webpack 是一种流行的模块打包器,一种用于将应用程序源代码打包成方便的块并将该代码从服务器加载到浏览器的工具.您可以使用 webpack 配置 Angular 2 网络应用程序(参见 this guide)。
从 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);
});
}
}
这只是动态加载脚本的示例代码,您可以根据需要自行定制和优化。
对于样式表,您应该使用 styleUrl 将其加载到组件中。
使用浏览器缓存: 当您使用浏览器缓存时,您的网页文件将存储在浏览器缓存中。您的页面对于重复访问者的加载速度会更快,共享这些相同资源的其他页面也会如此。更多信息 https://varvy.com/pagespeed/leverage-browser-caching.html
最小化 app.component.ts 中的代码: 最小化 app.component.ts 中的代码,当应用程序时,它总是 运行加载或重新加载。
在应用程序初始化中设置数据: 如果您在项目或组件中多次使用相同的 api 调用,
或者您依赖于多个组件中的相同数据,而不是多次调用 api 您可以做的就是保存
数据作为应用程序初始化服务中的对象。该服务将在整个项目中充当单身人士,而您
无需调用 api.
即可访问该数据
一步步懒加载模块
模块化结构: 我们要把我们的App分成独立的模块。例如,一个应用程序可能有一个用户端和一个管理端,每个端都有自己不同的组件和路由,所以我们将这两个端分成模块 admin.module.ts 和 user.module.ts.
根模块:每个 Angular 应用程序都有一个根模块 class。按照惯例,它是名为 app.module.ts 的文件中名为 AppModule 的 class,该模块将导入上述两个模块以及 bootstrap 的 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 { }
- 路线:现在在你的路线中你可以像下面这样指定
\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 路由时加载。因此,它将减少加载到浏览器中的负载大小,从而实现快速加载。
- 嵌套模块: 就像 app.module 每个模块都有自己的一组组件和路由。随着您的项目变得越来越大,在模块中嵌套模块是最好的优化方式,因为我们可以在需要时延迟加载这些模块。
请注意
以上代码仅作解释,完整示例请参考
https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html
因为它的 SPA 和 angular2 init 太慢了。而已。加上 RXjs、大量的 polifills 等。AOT 可以提供帮助,但很多 angular2 库无法使用它。 angular 万能真有帮助
尝试通过 运行 ng serve --sourcemap=false
禁用源映射
使用以下命令构建您的 angular 应用以获得最大的优化优势。
ng build --prod --aot --optimization --build-optimizer --vendor-chunk --common-chunk --extract-licenses --extract-css --source-map=false
基本上您将在 aot 模式下构建并使用 treeshaking 进行一些优化。
优化:启用构建输出的优化。
vendor-chunk:使用仅包含供应商库的单独包。
- common-chunk:使用一个单独的包,其中包含跨多个包使用的代码。
- extract-css:从全局样式中提取 css 到 css 文件而不是 js 文件。
- build-optimizer:在使用 'aot' 选项时启用@angular-devkit/build-optimizer 优化。
- source-map=false: 删除源映射也会减少包大小
Angular2 应用加载缓慢,如何提高加载性能?
我使用 Angular2,打字稿 html5。
目前我的应用程序需要 4 秒才能加载。 我使用 Firebase 托管并使用 cloudflare。
我正在做的事情/信息:
- 我压缩了图片。
- 我缩小css
- 我缩小js。
- 我在我的脚本上使用异步。
- 我的脚本在我的.
- 脚本大约 700kb
- 我使用 google 速度测试并获得 65%
- 我使用了我使用的库的缩小版本,例如bootstrap等
- 使用 systemjs。
- 这是我使用的种子应用程序:https://github.com/mgechev/angular-seed
流量:
应用程序加载时显示蓝屏(这是 bootstrap css),然后 4 秒后应用程序加载并运行得非常快。但加载需要 4 秒。似乎 systemjs 缩小到的 app.js 文件正在减慢整个应用程序,并且显示视图的速度不够快。
这是我的网站速度测试: https://www.webpagetest.org/result/161206_F5_N87/
这是我的网站:
如果您需要有关我的应用程序以及我可以做的任何其他事情的更多信息,请告诉我。
"code splitting"怎么样。
来自 Webpack 站点:
“对于大型 Web 应用程序,将所有代码放入单个文件中效率不高,尤其是如果仅在某些情况下需要某些代码块。Webpack 具有将代码库拆分为加载的“块”的功能按需。其他一些打包器称它们为“层”、“汇总”或“片段”。此功能称为“代码拆分”。
Link 这里:
https://webpack.github.io/docs/code-splitting.html
请注意,Angular CLI 使用 Webpack。
此外,请确保如果您的应用通过数据调用进行引导,则您不会阻止等待这些调用 return 的组件的呈现。承诺、异步等
如果没有 hands-on 整个代码库和后端,很难诊断出您遇到的确切问题(正如其他人所建议的,问题可能根本不是 angular)。
话虽如此,我强烈建议您开始使用 angular-cli。它由 angular 团队设计,旨在完成您需要在 easy-to-use 命令行界面中完成的所有事情。所以我的回答是基于 angular-cli 的使用。
以下是您可以为生产环境优化 ng2 项目的一般操作:
1) 提前 (AoT) 编译 - Bundling/Minification/Tree-shaking
看,忘掉配置一堆 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
inline.d41d8cd98f00b204e980.bundle.js.gz
vendor.d41d8cd98f00b204e980.bundle.js.gz
main.d41d8cd98f00b204e980.bundle.js.gz
Angular 的 AOT 编译将自动对您的代码执行 "tree shaking" 并删除任何未使用的引用。例如,您可能在项目中使用了 lodash,但您可能只使用了几个 lodash 函数; tree shaking 将 trim 移除最终构建中不需要的 lodash 中所有未使用的部分。最重要的是,AOT 编译将 pre-compile 你所有的代码和视图,这意味着浏览器运行 ng2 应用所需的时间更少。 Click here 有关 angular 的 AOT 编译的更多信息。
2) 应用的延迟加载部分 如果您进一步将您的应用程序分成不同的部分,您不需要在您的应用程序首次加载时加载所有内容。您可以为您的应用程序指定不同的模块,然后可以将这些模块(由 angular-cli aot 编译器)捆绑到不同的块中。阅读 here 以了解如何将您的项目组织成模块,您可以将这些模块编译成仅在需要时加载的卡盘。 Angular-cli 将为您管理这些块的创建。
3) Angular 通用 现在,如果你真的想让你的加载时间非常快,那么你将要考虑实施 Angular Universal,这是在你在服务器上编译你的初始视图时。我没有使用 Angular Universal,因为我已经能够通过步骤 1 和 2 实现快速加载时间。但它是 ng2 工具集中的一个令人兴奋的选项。请记住,您没有在服务器上编译或 运行 ng2 应用程序,而是在服务器端编译初始视图,以便用户快速收到 html 的震动,因此用户认为加载时间是非常快(即使满载仍然会落后一点)。此步骤并不排除对其他步骤的需要。作为奖励,Angular Universal 也应该有助于 SEO。
4)二次捆绑
如果我不使用延迟加载,我通常会进一步捆绑AOT编译生成的分发文件。因此,我创建了一个 main.bundle.js 文件,其中包含 inline.js、vendor.js 和 main.js 文件。我为此使用 gulp。
单页应用程序通常在加载时需要更多时间,因为它一次加载所有必要的东西。
我也遇到过同样的问题,我的团队使用以下方法优化了我们的项目,从 8 秒加载到 2 秒。
延迟加载模块:延迟加载模块有助于减少启动时间。使用延迟加载,我们的应用程序不需要一次加载所有内容,它只需要加载用户希望在应用程序首次加载时看到的内容。延迟加载的模块只会在用户导航到他们的路线时加载。 Angular2 在其最终版本 RC5 中引入了模块。 请参阅下面的分步指南。
Aot 编译: 使用 AoT,浏览器会下载应用程序的预编译版本。浏览器加载可执行代码,以便它可以立即呈现应用程序,而无需先等待编译应用程序。
它减少了负载大小: 如果应用程序已经编译,则无需下载 Angular 编译器。编译器大约是 Angular 本身的一半,因此省略它会大大减少应用程序的负载。有关详细信息,请参阅 this。
Webpack : Webpack 是一种流行的模块打包器,一种用于将应用程序源代码打包成方便的块并将该代码从服务器加载到浏览器的工具.您可以使用 webpack 配置 Angular 2 网络应用程序(参见 this guide)。
从 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);
});
}
}
这只是动态加载脚本的示例代码,您可以根据需要自行定制和优化。 对于样式表,您应该使用 styleUrl 将其加载到组件中。
使用浏览器缓存: 当您使用浏览器缓存时,您的网页文件将存储在浏览器缓存中。您的页面对于重复访问者的加载速度会更快,共享这些相同资源的其他页面也会如此。更多信息 https://varvy.com/pagespeed/leverage-browser-caching.html
最小化 app.component.ts 中的代码: 最小化 app.component.ts 中的代码,当应用程序时,它总是 运行加载或重新加载。
在应用程序初始化中设置数据: 如果您在项目或组件中多次使用相同的 api 调用, 或者您依赖于多个组件中的相同数据,而不是多次调用 api 您可以做的就是保存 数据作为应用程序初始化服务中的对象。该服务将在整个项目中充当单身人士,而您 无需调用 api.
即可访问该数据
一步步懒加载模块
模块化结构: 我们要把我们的App分成独立的模块。例如,一个应用程序可能有一个用户端和一个管理端,每个端都有自己不同的组件和路由,所以我们将这两个端分成模块 admin.module.ts 和 user.module.ts.
根模块:每个 Angular 应用程序都有一个根模块 class。按照惯例,它是名为 app.module.ts 的文件中名为 AppModule 的 class,该模块将导入上述两个模块以及 bootstrap 的 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 { }
- 路线:现在在你的路线中你可以像下面这样指定
\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 路由时加载。因此,它将减少加载到浏览器中的负载大小,从而实现快速加载。
- 嵌套模块: 就像 app.module 每个模块都有自己的一组组件和路由。随着您的项目变得越来越大,在模块中嵌套模块是最好的优化方式,因为我们可以在需要时延迟加载这些模块。
请注意
以上代码仅作解释,完整示例请参考 https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html
因为它的 SPA 和 angular2 init 太慢了。而已。加上 RXjs、大量的 polifills 等。AOT 可以提供帮助,但很多 angular2 库无法使用它。 angular 万能真有帮助
尝试通过 运行 ng serve --sourcemap=false
使用以下命令构建您的 angular 应用以获得最大的优化优势。
ng build --prod --aot --optimization --build-optimizer --vendor-chunk --common-chunk --extract-licenses --extract-css --source-map=false
基本上您将在 aot 模式下构建并使用 treeshaking 进行一些优化。
优化:启用构建输出的优化。
vendor-chunk:使用仅包含供应商库的单独包。
- common-chunk:使用一个单独的包,其中包含跨多个包使用的代码。
- extract-css:从全局样式中提取 css 到 css 文件而不是 js 文件。
- build-optimizer:在使用 'aot' 选项时启用@angular-devkit/build-optimizer 优化。
- source-map=false: 删除源映射也会减少包大小