Angular 2 Lazy Loading 別讓載入速度拖垮你!
- 2016-12-23
- Liu, An-Chi 劉安齊
前言
Lazy loading 是指從一個資料物件通過方法獲得裡面的一個屬性物件時,這個對應物件實際並沒有隨其父資料物件建立時一起儲存在執行空間中,而是在其讀取方法第一次被呼叫時才從其他資料來源中載入到執行空間中,這樣可以避免過早地匯入過大的資料物件但並沒有使用的空間占用浪費。
Lazy loading 在載入非常多不同內容時非常有感。當一個網站包含的東西越多,開啟的速度也會越慢,當網頁從上到下讀取,當遇到了比較大的元件時,讀取速度上絕不會像讀取小元件一樣順暢,常常因為所含的組件太多,導致網站讀取速度變慢,這網站真的是吃了悶虧。那是否有辦法改善這種因為讀取速度而造成網站開啟太慢的問題呢?
實現
Angular2 中 , lazy loading 已經被建在 Router 裡了。 接下來要花幾個步驟:
- 指定 app.routing.ts 中要 lazy load 的路由 (routes)
- 建立 Component 路由文件
- 調整要被 lazy load 的 module 的內容
路徑物件
為了區分 lazy loading,我們要建立一個路徑物件包含 loadChildren
特性。在這物件裡面要設定 module 的名稱和路徑。
//app.routes.ts
import {Routes, RouterModule} from "@angular/router";
import {ModuleWithProviders} from "@angular/core";
const appRoutes: Routes = [
// 假設有首頁
{ path: "", redirectTo: "home", pathMatch: "full" },
// 要處理的 Product APP 頁面
{ path: "product", loadChildren: "app/product/product.module#ProductModule" }
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
這樣代表 URL 會從 /product
開始, angular 路由將會得到 module 檔案 app/product/product.module
並預期有 ProductModule
這個 class。
路由 Module
//product/product.routing.ts
import {RouterModule} from "@angular/router";
import {ModuleWithProviders} from "@angular/core";
import {ProductComponent} from "./product.component";
// 小零件 ( 各種用到的東西 )
import {ProductsListComponent} from "./products-list.component";
import {ProductDetailsComponent} from "./product-details.component";
const routes = [
{
path: "", //設定根目錄為這一層
component: ProductComponent,
// Product 包含的小組件們
children: [
{path: "", component: ProductsListComponent},
{path: ":id", component: ProductDetailsComponent}
]
}
];
export const routing: ModuleWithProviders = RouterModule.forChild(routes);
設定 Component
定義 ProductComponent
//product/product.component.ts
import {Component} from "@angular/core";
@Component({
template: <my-nav></my-nav> <h1>Products</h1> <router-outlet></router-outlet>
})
export class ProductComponent {}
router-outlet
會呈現這個 module 內容
有 Lazy Load 的 Module
//product/product.module.ts
import {NgModule} from "@angular/core";
import {ProductsService} from "./products.service";
import {ProductsListComponent} from "./products-list.component";
import {ProductDetailsComponent} from "./product-details.component";
import {routing} from "./product.routing";
import {ProductComponent} from "./product.component";
@NgModule({
declarations: [ProductComponent, ProductsListComponent, ProductDetailsComponent],
imports: [routing],
providers: [ProductsService],
})
export class ProductModule {}
這邊會用到 product.routing
的 routing
。
測試
假設你的網站有三個 Module: home
project
about
那加入 lazy loading 的前後差異大概會是這樣
加入前
加入後
原因是因為加入 lazy loading 所以會先只載入 home
根 about
,在這邊我們假設他們兩個非常輕量,那就會使得整個網頁載入的順暢度整體提升,而比較大的 project
則在之後載入,就不會拖垮速度了!
補充:模板載入組件
方式
假設有兩個 Components fast
& slow
//src/components/fast.ts
import { Component } from '@angular/core';
@Component({
selector: 'fast',
template: <p>Fast Content</p>
})
export class FastComponent { }
//src/components/slow.ts
import { Component } from '@angular/core';
@Component({
selector: 'slow',
template: `
<p>Slow Content</p>
`
})
export class SlowComponent { }
在 Template 裡面載入 Component 是最常用載入方式。非常簡單,只需要存放相應的 selector
,模板引擎就會自己找到並編譯。
//app.component.ts
import {Component} from '@angular/core'
import {FastComponent} from 'src/components/fast'
import {SlowComponent} from 'src/components/slow'
@Component({
selector: 'template-load',
template: <h1>方式一:template 動態載入</h1> <fast></fast> <slow></slow>
,
directives: [ FastComponent, SlowComponent ]
})
export class TemplateLoadComponent {
constructor() {
}
}