Lazy Loading Module และ Route Guards (canActivate)

Lazy Loading คือการแยกโค้ดตาม Feature แล้วโหลด Module เฉพาะเมื่อผู้ใช้เข้า Route นั้น ส่วน Route Guard คือกลไกตรวจเงื่อนไขก่อนอนุญาตให้เข้า ออก หรือโหลดข้อมูลของ Route

Timeline/ประวัติศาสตร์

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart LR
  subgraph Era1["ยุค Bundle เดียว / Single Bundle"]
    A["โหลดทุกอย่างตอนเริ่ม
Large Initial Bundle"] end subgraph Era2["ยุค Feature Module / Modular App"] B["Feature Module
แยกตามฟีเจอร์"] C["Lazy Loading
โหลดเมื่อเข้า route"] end subgraph Era3["ยุค Protected Route / Guarded App"] D["CanActivate
ตรวจสิทธิ์"] E["Resolver
โหลดข้อมูลก่อนเข้า"] end A --> B --> C --> D --> E

แนวคิดสำคัญ

ตารางเปรียบเทียบ Route Guard/Resolver

กลไก ทำงานเมื่อใด คืนค่า เหมาะกับ
canActivate ก่อนเข้า Route boolean/UrlTree ตรวจ login/role
canDeactivate ก่อนออกจาก Route boolean ยืนยันฟอร์มยังไม่ save
canLoad ก่อนโหลด Module boolean กันโหลด feature
resolve ก่อน Component แสดง data โหลดข้อมูลล่วงหน้า

Mermaid Diagram: Lazy Route Decision

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart TD
  A["ผู้ใช้เข้า /admin
Navigate"] --> B["CanActivate Guard
ตรวจสิทธิ์"] B -->|ผ่าน / Allow| C["Lazy Load Module
โหลด AdminModule"] B -->|ไม่ผ่าน / Deny| D["Redirect /login
ส่งไปหน้า Login"] C --> E["Resolver
โหลดข้อมูล"] E --> F["Admin Component
แสดงหน้า"]

Code Example

// app-routing.module.ts
// Lazy load feature module เมื่อเข้า /admin
const routes: Routes = [
  {
    path: 'admin',
    canActivate: [authGuard],
    loadChildren: () =>
      import('./admin/admin.module').then(m => m.AdminModule)
  }
];
// auth.guard.ts
// Guard แบบ functional ตรวจว่าผู้ใช้ login แล้วหรือยัง
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';

export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  const router = inject(Router);

  if (auth.isLoggedIn()) {
    return true;
  }

  return router.createUrlTree(['/login']);
};

// ตัวอย่างการใช้งาน:
// เพิ่ม canActivate: [authGuard] ใน route ที่ต้องการป้องกัน
// navigation example
// ส่ง state ผ่าน NavigationExtras
this.router.navigate(['/checkout'], {
  state: { fromCart: true }
});

กิจกรรมท้ายบท

กลับสัปดาห์ที่ 9