简介
延迟加载(Lazy Loading)是一种按需加载模块的策略,即仅在用户实际访问时加载所需模块。该策略能够显著提升 Angular 应用的性能,并有效减小初始打包体积——在大型项目中,优化效果尤为突出。

默认情况下,Angular 采用“急切加载”(Eager Loading)模式,即在应用启动前加载所有模块。对于小型项目这或许足够,但随着模块数量增加,加载时间会迅速成为性能瓶颈。事实上,许多开发者容易忽略这一关键优化点。
接下来,我们将逐步介绍如何在 Angular 应用中配置并实现懒加载路由(Lazy Loading Routes)。
先决条件
要完成本教程,你需要具备以下条件:
- 在本地环境中安装 Node.js(具体安装步骤可参考《如何安装 Node.js 并创建本地开发环境》)。
- 具备基本的 Angular 项目搭建知识。
本教程已在 Node v16.4.0、npm v7.19.0、@angular/core v12.1.0 和 @angular/router v12.1.0 环境下完成测试验证。
步骤 1 – 设置项目
懒加载的路由不能定义在根应用模块中,而应放置在独立的功能模块内,这是实现懒加载的基本设计原则。
首先,使用 Angular CLI 创建一个带路由的新项目:
ng new angular-lazy-loading-example --routing --style=css --skip-tests
接着,进入项目目录:
cd angular-lazy-loading-example
下一步,生成一个新的功能模块:
ng generate module shop --route shop --module app.module
在 shop 功能模块中,我们需要创建以下三个组件:
第一个是购物车组件(Cart):
ng generate component shop/cart
第二个是结算组件(Checkout):
ng generate component shop/checkout
第三个是确认组件(Confirm):
ng generate component shop/confirm
这三个组件都将位于 shop 目录下。至此,项目已准备好一个包含 3 个组件的 shop 功能模块。
步骤 2 – 使用 loadChildren
在主路由配置中,核心代码如下所示:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: 'shop', loadChildren: () => import('./shop/shop.module').then(m => m.ShopModule) },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
自 Angular 8 起,loadChildren 接受一个函数,该函数利用动态导入(Dynamic Import)语法加载模块,仅在用户实际访问对应路由时才会发起请求。动态导入基于 Promise 机制,成功加载模块后即可调用其类。
步骤 3 – 在功能模块中设置路由配置
接下来,最后一步:配置功能模块自身的路由。
参考以下示例:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CartComponent } from './cart/cart.component';
import { CheckoutComponent } from './checkout/checkout.component';
import { ConfirmComponent } from './confirm/confirm.component';
const routes: Routes = [
{ path: '', component: CartComponent },
{ path: 'checkout', component: CheckoutComponent },
{ path: 'confirm', component: ConfirmComponent },
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ShopRoutingModule { }
最后,在功能模块中引入路由时,必须使用 RouterModule.forChild 方法,而非 forRoot:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ShopRoutingModule } from './shop-routing.module';
import { ShopComponent } from './shop.component';
import { CartComponent } from './cart/cart.component';
import { CheckoutComponent } from './checkout/checkout.component';
import { ConfirmComponent } from './confirm/confirm.component';
@NgModule({
declarations: [
ShopComponent,
CartComponent,
CheckoutComponent,
ConfirmComponent,
],
imports: [
CommonModule,
ShopRoutingModule
]
})
export class ShopModule { }
现在,你可以使用 routerLink 指令导航到 /shop、/shop/checkout 或 /shop/confirm 等路径。请注意,模块只会在首次访问这些路径时按需加载。
在终端中启动开发服务器:
ng serve
你会看到生成的打包文件,包括一个 main.js 和一个独立的懒加载文件 src_app_shop_shop_module_ts.js:
初始块文件 | 名称 | 大小
vendor.js | vendor | 2.38 MB
polyfills.js | polyfills | 128.58 kB
main.js | main | 57.18 kB
runtime.js | runtime | 12.55 kB
styles.css | styles | 119 字节
| 初始总计 | 2.58 MB
延迟块文件 | 名称 | 大小
src_app_shop_shop_module_ts.js | - | 10.62 kB
在浏览器中访问 localhost:4200,打开 DevTools 的网络面板进行验证:初始加载时不会出现懒加载块;当你导航到 /shop 时,src_app_shop_shop_module_ts.js 就会出现在网络请求中。恭喜,你的应用现已支持懒加载功能。
结论
本文完整介绍了在 Angular 应用中配置懒加载路由的整个流程,涵盖项目搭建、模块拆分以及动态加载实现,每个步骤都清晰明了。
接下来,你可以进一步学习如何测试包含依赖的组件、测试服务,以及如何使用模拟(Mock)、存根(Stub)和间谍(Spy)等测试技术。
更详细的官方文档也是很好的学习资源,其中包含许多关于懒加载的进阶指南。
