angular2及以上提供了两个非常实用的特性:懒加载和预加载
一、理论
1. 什么是懒加载?
懒加载也叫延迟加载,在访问到这个模块的时候,Angular才会加载这个模块。
2. 为什么要使用懒加载?
我们知道一个项目做得比较大的时候,模块组件比较多的时候,代码的体积也就相应增加,执行时间相应延长,这样会使得页面首次打开加载时长增大,用户体验下降。使用懒加载可以很好地解决这个问题,让开始只加载需要用户需要的代码,后续用户交互时再加载对应的代码,可以大幅提升首屏用户体验,让用户感觉到首屏很快,但是随之带了的是用户第一次去查看懒加载模块时,这个时候懒加载模块菜开始加载,会有个加载等待的延迟,那么就需要用到预加载。
3. 什么是预加载?
预加载也叫做提前加载,就是将需要加载却还没加载(懒加载)的代码在空闲时去加载。
4. 为什么要使用预加载以及和懒加载的关系?
如果没使用懒加载将无法使用预加载,因为预加载就是提前加载懒加载的那部分代码。
预加载是自己加载完了再去加载其他模块,是在空闲时去加载,不影响
用户还没访问这个模块之前就将代码加载好,用户访问的时候回觉得快。
懒加载配合预加载一起用,这样才能达到最大的用户体验。
5. Angular2中懒加载和预加载所使用的技术
在angular2中实现懒加载和预加载都是使用路由配置来实现的
懒加载核心是要靠路由配置中的
loadChildren: '模块路径#模块名'来实现
forRoot() 与 forChild()
forRoot()只能在根路由模块使用一次 全局注入路由器
forChild()各个特性模块中使用 没有注入器配置,只有指令
预加载主要靠路由配置中的{preloadingStrategy: PreloadAllModules}
PreloadAllModules意思是预先加载策略是预先加载所有的module。还有一种是NoPreloading,也就是没有预加载
二、在Angular2及以上中的实践
1. Angular中使用懒加载
首先创建一个angular应用
ng new appName --routing
创建两个带路由的特性模块
ng generate module customers --routing
ng generate module orders --routing
分别向特性模块中添加组件
ng generate component customers/customer-list
ng generate component orders/order-list
将组件添加到路由和模块中并将路由模块也添加到模块中
特性模块的路由配置customers-routing.module.ts
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { CustomerListComponent } from './customer-list/customer-list.component'; const routes: Routes = [ { path: '', component: CustomerListComponent } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class CustomersRoutingModule { }
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { CustomersRoutingModule } from './customers-routing.module'; import { CustomerListComponent } from './customer-list/customer-list.component'; @NgModule({ imports: [ CommonModule, CustomersRoutingModule ], declarations: [CustomerListComponent] }) export class CustomersModule { }重复这个步骤以导入 OrdersListComponent,并为 orders-routing.module.ts 配置路由树组
简单UI app.component.html
<button routerLink="/customers">Customers</button> <button routerLink="/orders">Orders</button> <button routerLink="">Home</button> <router-outlet></router-outlet>主路由文件中配置 app-routing.module.ts
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [{ path: 'customers', loadChildren: './customers/customers.module#CustomersModule' },{ path: 'orders', loadChildren: './orders/orders.module#OrdersModule' },{ path: '', redirectTo: '', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes, {useHash:true})], exports: [RouterModule] }) export class AppRoutingModule {}2. Angular中使用预加载策略
首先已经使用了懒加载
然后在主路由配置中 app-routing.module.ts
import { Routes, RouterModule, PreloadAllModules } from '@angular/router'; @NgModule({ imports: [RouterModule.forRoot(routes, { useHash: true, preloadingStrategy: PreloadAllModules })], exports: [RouterModule] })上述代码意思就是预先加载策略是预先加载所有的module
3. 自定义预加载策略
但是使用PreloadAllModules的缺点是不能控制哪些模块加载哪些模块不加载,通过自定义预加载策略定义模块是否预加载
新增文件 custom-preloading-strategy.ts
import { Route } from '@angular/router'; import { PreloadingStrategy } from '@angular/router'; import { Observable } from 'rxjs/Rx'; export class CustomPreloadingStrategy implements PreloadingStrategy { preload(route: Route, load: Function): Observable<any> { return route.data && route.data.preload ? load() : Observable.of(null); } }
然后,修改 app-routing.module.ts 使用这个自定义策略。需要注意的是,您还需要在 prodivers 中添加这个类。以实现依赖注入。
import { CustomPreloadingStrategy } from './custom-preloading-strategy'; // 预加载 const routes: Routes = [{ path: 'customers', loadChildren: './customers/customers.module#CustomersModule', data: {preload: true} },{ path: 'orders', loadChildren: './orders/orders.module#OrdersModule' },{ path: '', redirectTo: '', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes, { useHash: true, preloadingStrategy: CustomPreloadingStrategy // 预加载 })], exports: [RouterModule], providers: [CustomPreloadingStrategy] })扩展知识
一个Angular项目中是否使用了懒加载和预加载就看从浏览器打开应用后控制台是否加载一些chunk的js文件,有的话就是使用了懒加载和预加载,如果只是在切换路由时出现chunk文件,可能只是使用了懒加载,否则都没使用。
发表评论: