การแยกโค้ดระดับเส้นทางใน Angular

ปรับปรุงประสิทธิภาพของแอปโดยใช้การแยกโค้ดระดับเส้นทาง

โพสต์นี้อธิบายวิธีตั้งค่าการแยกโค้ดระดับเส้นทางในแอปพลิเคชัน Angular ซึ่งจะช่วยลดขนาดแพ็กเกจ JavaScript และปรับปรุงเวลาในการตอบสนองได้อย่างมาก

คุณดูตัวอย่างโค้ดจากบทความนี้ได้ใน GitHub ดูตัวอย่างการกำหนดเส้นทางแบบ Eager ได้ในสาขา Eager ตัวอย่างการแยกโค้ดระดับเส้นทางอยู่ในสาขา Lazy

เหตุใดการแยกโค้ดจึงสำคัญ

ความซับซ้อนที่เพิ่มขึ้นเรื่อยๆ ของเว็บแอปพลิเคชันทำให้ปริมาณ JavaScript ที่ส่งไปยังผู้ใช้เพิ่มขึ้นอย่างมาก ไฟล์ JavaScript ขนาดใหญ่สามารถทำให้การโต้ตอบล่าช้าอย่างเห็นได้ชัด จึงอาจเป็นทรัพยากรที่มีค่าใช้จ่ายสูง โดยเฉพาะในอุปกรณ์เคลื่อนที่

วิธีที่มีประสิทธิภาพที่สุดในการลดขนาดแพ็กเกจ JavaScript โดยไม่ลดทอนฟีเจอร์ในแอปพลิเคชันคือการใช้การแยกโค้ดอย่างเข้มงวด

การแยกโค้ดช่วยให้คุณแบ่ง JavaScript ของแอปพลิเคชันออกเป็นหลายๆ ส่วนที่เชื่อมโยงกับเส้นทางหรือฟีเจอร์ต่างๆ ได้ วิธีนี้จะส่งเฉพาะ JavaScript ที่ผู้ใช้ต้องการในระหว่างการโหลดแอปพลิเคชันครั้งแรก ซึ่งช่วยให้ใช้เวลาโหลดน้อยลง

เทคนิคการแยกโค้ด

การแยกโค้ดทำได้ 2 ระดับ ได้แก่ ระดับคอมโพเนนต์และระดับเส้นทาง

  • ในการแยกโค้ดระดับคอมโพเนนต์ คุณจะย้ายคอมโพเนนต์ไปยังกลุ่ม JavaScript ของตนเองและโหลดแบบ Lazy Load เมื่อจำเป็น
  • ในการแยกโค้ดระดับเส้นทาง คุณจะรวมฟังก์ชันการทำงานของแต่ละเส้นทางไว้ในกลุ่มแยกต่างหาก เมื่อผู้ใช้ไปยังส่วนต่างๆ ของแอปพลิเคชัน ระบบจะดึงข้อมูลกลุ่มที่เชื่อมโยงกับเส้นทางแต่ละเส้นทางและรับฟังก์ชันการทำงานที่เกี่ยวข้องเมื่อต้องการ

โพสต์นี้มุ่งเน้นที่การตั้งค่าการแยกโค้ดระดับเส้นทางใน Angular

แอปพลิเคชันตัวอย่าง

ก่อนที่จะเจาะลึกวิธีใช้การแยกโค้ดระดับเส้นทางใน Angular มาดูแอปตัวอย่างกันก่อน

ดูการติดตั้งใช้งานโมดูลของแอป ภายใน AppModule มีการกำหนดเส้นทาง 2 เส้นทาง ได้แก่ เส้นทางเริ่มต้นที่เชื่อมโยงกับ HomeComponent และเส้นทาง nyan ที่เชื่อมโยงกับ NyanComponent ดังนี้

@NgModule({
  ...
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: '',
        component: HomeComponent,
        pathMatch: 'full'
      },
      {
        path: 'nyan',
        component: NyanComponent
      }
    ])
  ],
  ...
})
export class AppModule {}

การแยกโค้ดระดับเส้นทาง

หากต้องการตั้งค่าการแยกโค้ด คุณต้องเปลี่ยนโครงสร้างภายในโค้ดของเส้นทาง nyan ที่โหลดทันที

Angular CLI เวอร์ชัน 8.1.0 สามารถทำทุกอย่างให้คุณได้ด้วยคำสั่งนี้

ng g module nyan --module app --route nyan

ซึ่งจะสร้างสิ่งต่อไปนี้ - โมดูลการกำหนดเส้นทางใหม่ชื่อ NyanModule - เส้นทางใน AppModule ชื่อ nyan ซึ่งจะโหลด NyanModule แบบไดนามิก - เส้นทางเริ่มต้นใน NyanModule - คอมโพเนนต์ชื่อ NyanComponent ซึ่งจะแสดงผลเมื่อผู้ใช้เข้าถึงเส้นทางเริ่มต้น

มาทำตามขั้นตอนเหล่านี้ด้วยตนเองเพื่อให้เข้าใจการใช้การแยกโค้ดกับ Angular ได้ดียิ่งขึ้นกัน

เมื่อผู้ใช้ไปยังเส้นทาง nyan เราเตอร์จะแสดงผล NyanComponent ในเอาต์เล็ตของเราเตอร์

หากต้องการใช้การแยกโค้ดระดับเส้นทางใน Angular ให้ตั้งค่าพร็อพเพอร์ตี้ loadChildren ของการประกาศเส้นทางและรวมเข้ากับการนําเข้าแบบไดนามิก ดังนี้

{
  path: 'nyan',
  loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}

ซึ่งมีความแตกต่างที่สำคัญ 2 ประการจากเส้นทางแบบกระตือรือร้น ดังนี้

  1. คุณตั้งค่า loadChildren แทนที่จะเป็น component เมื่อใช้การแยกโค้ดระดับเส้นทาง คุณต้องชี้ไปยังโมดูลที่โหลดแบบไดนามิกแทนคอมโพเนนต์
  2. ใน loadChildren เมื่อแก้ไขสัญญาแล้ว คุณจะแสดงผล NyanModule แทนที่จะชี้ไปยัง NyanComponent

ข้อมูลโค้ดด้านบนระบุว่าเมื่อผู้ใช้ไปยัง nyan Angular ควรโหลด nyan.module จากไดเรกทอรี nyan แบบไดนามิก และแสดงผลคอมโพเนนต์ที่เชื่อมโยงกับเส้นทางเริ่มต้นที่ประกาศไว้ในโมดูล

คุณสามารถเชื่อมโยงเส้นทางเริ่มต้นกับคอมโพเนนต์ได้โดยใช้การประกาศนี้

import { NgModule } from '@angular/core';
import { NyanComponent } from './nyan.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [NyanComponent],
  imports: [
    RouterModule.forChild([{
      path: '',
      pathMatch: 'full',
      component: NyanComponent
    }])
  ]
})
export class NyanModule {}

โค้ดนี้จะแสดง NyanComponent เมื่อผู้ใช้ไปยัง https://example.com/nyan

วิธีตรวจสอบว่าเราเตอร์ Angular ดาวน์โหลด nyan.module แบบ Lazy ในสภาพแวดล้อมภายในเครื่อง

  1. กด `Control+Shift+J` (หรือ `Command+Option+J` บน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาเว็บ
  2. คลิกแท็บเครือข่าย

  3. คลิก NYAN ในแอปตัวอย่าง

  4. โปรดทราบว่าไฟล์ nyan-nyan-module.js จะปรากฏในแท็บเครือข่าย

การโหลดแบบ Lazy Loading ของแพ็กเกจ JavaScript ที่มีการแยกโค้ดระดับเส้นทาง

ดูตัวอย่างนี้ใน GitHub

แสดงภาพหมุน

ตอนนี้เมื่อผู้ใช้คลิกปุ่ม NYAN แอปพลิเคชันจะไม่ระบุว่ากำลังโหลด JavaScript ในเบื้องหลัง หากต้องการแสดงความคิดเห็นของผู้ใช้ขณะโหลดสคริปต์ คุณอาจต้องเพิ่มไอคอนหมุน

โดยเริ่มจากการเพิ่มมาร์กอัปสำหรับตัวบ่งชี้ภายในองค์ประกอบ router-outlet ใน app.component.html ดังนี้

<router-outlet>
  <span class="loader" *ngIf="loading"></span>
</router-outlet>

จากนั้นเพิ่มคลาส AppComponent เพื่อจัดการเหตุการณ์การกำหนดเส้นทาง คลาสนี้จะตั้งค่าแฟล็ก loading เป็น true เมื่อได้ยินเหตุการณ์ RouteConfigLoadStart และตั้งค่าแฟล็กเป็น false เมื่อได้ยินเหตุการณ์ RouteConfigLoadEnd

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  loading: boolean;
  constructor(router: Router) {
    this.loading = false;
    router.events.subscribe(
      (event: RouterEvent): void => {
        if (event instanceof NavigationStart) {
          this.loading = true;
        } else if (event instanceof NavigationEnd) {
          this.loading = false;
        }
      }
    );
  }
}

ในตัวอย่างด้านล่าง เราได้เพิ่มเวลาในการตอบสนอง 500 มิลลิวินาทีเพื่อให้คุณเห็นภาพหมุนที่ทำงานอยู่

บทสรุป

คุณลดขนาดแพ็กเกจของแอปพลิเคชัน Angular ได้โดยใช้การแยกโค้ดระดับเส้นทาง ดังนี้

  1. ใช้เครื่องมือสร้างโมดูลที่โหลดแบบ Lazy Loading ของ Angular CLI เพื่อสร้างโครงสร้างเส้นทางที่โหลดแบบไดนามิกโดยอัตโนมัติ
  2. เพิ่มสัญญาณบอกสถานะการโหลดเมื่อผู้ใช้ไปยังเส้นทางที่โหลดแบบ Lazy เพื่อแสดงว่ามีการดำเนินการที่ดำเนินอยู่