单页应用程序在加载时通常需要更多时间,因为它一次加载所有必要的东西。
我也遇到了同样的问题,我的团队使用以下方法将我们的项目从 8 秒加载到 2 秒优化。
延迟加载模块:延迟加载模块有助于减少启动时间。通过延迟加载,我们的应用程序不需要一次加载所有内容,它只需要加载用户在应用程序首次加载时期望看到的内容。延迟加载的模块只有在用户导航到他们的路线时才会被加载。 Angular2 在其最终版本 RC5 中引入了模块。 请参阅下面的分步指南。
-
Aot 编译: 使用 AoT,浏览器会下载应用程序的预编译版本。浏览器加载可执行代码,因此它可以立即呈现应用程序,而无需等待先编译应用程序。
它减少了负载大小: 如果应用程序已经编译,则无需下载 Angular 编译器。编译器大约是 Angular 本身的一半,因此省略它会大大减少应用程序的负载。欲了解更多信息,请参阅this。
Webpack : Webpack 是一种流行的模块打包器,它是一种将应用程序源代码打包成方便的块并将该代码从服务器加载到浏览器中的工具。您可以使用 webpack 配置您的 Angular 2 Web 应用程序(请参阅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 即可访问该数据。
逐步延迟加载模块
-
模块化结构:我们必须将我们的应用程序分成单独的模块。例如,一个应用程序可能有一个用户端和一个管理端,每个端都有自己不同的组件和路由,所以我们将这两个端分成模块 admin.module.ts 和 user.module.ts。
根模块:每个 Angular 应用程序都有一个根模块类。按照惯例,它是一个名为 AppModule 的类,位于一个名为 app.module.ts 的文件中,该模块将导入上述两个模块以及用于引导的 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