ปรับปรุงประสิทธิภาพของแอปโดยใช้การแยกโค้ดระดับเส้นทาง
โพสต์นี้อธิบายวิธีตั้งค่าการแยกโค้ดระดับเส้นทางในแอปพลิเคชัน Angular ซึ่งจะช่วยลดขนาดกลุ่ม JavaScript และปรับปรุงเวลาในการตอบสนองได้อย่างมาก
ดูตัวอย่างโค้ดจากบทความนี้ได้ใน GitHub ตัวอย่างการกำหนดเส้นทางแบบด่วนมีอยู่ในสาขาแบบด่วน ตัวอย่างการแยกโค้ดระดับเส้นทางอยู่ในสาขาแบบ Lazy
เหตุผลที่การแยกโค้ดสำคัญ
ความซับซ้อนที่เพิ่มขึ้นเรื่อยๆ ของเว็บแอปพลิเคชันส่งผลให้ปริมาณ JavaScript ที่ส่งไปยังผู้ใช้เพิ่มขึ้นอย่างมาก ไฟล์ JavaScript ขนาดใหญ่อาจทำให้การโต้ตอบล่าช้าอย่างเห็นได้ชัด จึงอาจเป็นทรัพยากรที่มีราคาแพง โดยเฉพาะอย่างยิ่งในอุปกรณ์เคลื่อนที่
วิธีที่มีประสิทธิภาพที่สุดในการลดขนาดกลุ่ม JavaScript โดยไม่ลดฟีเจอร์ในแอปพลิเคชันของคุณคือการแยกโค้ดอย่างหนัก
การแยกโค้ดช่วยให้คุณแบ่ง JavaScript ของแอปพลิเคชันออกเป็นหลายกลุ่มที่เชื่อมโยงกับเส้นทางหรือฟีเจอร์ต่างๆ ได้ วิธีนี้ส่งเฉพาะ JavaScript ที่ผู้ใช้จําเป็นต้องใช้ระหว่างการโหลดแอปพลิเคชันครั้งแรกเท่านั้น ซึ่งช่วยให้เวลาในการโหลดต่ำ
เทคนิคการแยกโค้ด
การแยกโค้ดทำได้ 2 ระดับ ได้แก่ ระดับคอมโพเนนต์และระดับเส้นทาง
- ในการแยกโค้ดระดับคอมโพเนนต์ คุณจะย้ายคอมโพเนนต์ไปยังกลุ่ม JavaScript ของตัวเองและโหลดแบบเลื่อนเวลาเมื่อจําเป็น
- ในการแยกโค้ดระดับเส้นทาง คุณจะรวมฟังก์ชันการทำงานของแต่ละเส้นทางไว้ในกลุ่มแยกต่างหาก เมื่อผู้ใช้ไปยังส่วนต่างๆ ของแอปพลิเคชัน ระบบจะดึงข้อมูลส่วนที่เชื่อมโยงกับแต่ละเส้นทางและรับฟังก์ชันการทำงานที่เกี่ยวข้องเมื่อผู้ใช้ต้องการ
โพสต์นี้มุ่งเน้นที่การตั้งค่าการแยกระดับเส้นทางใน 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 อย่างจากเส้นทางที่พร้อมใช้งานทันทีมีดังนี้
- คุณตั้งค่าเป็น
loadChildren
แทนcomponent
เมื่อใช้การแยกโค้ดระดับเส้นทาง คุณต้องชี้ไปยังโมดูลที่โหลดแบบไดนามิกแทนคอมโพเนนต์ - ใน
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 Router ดาวน์โหลด nyan.module
แบบล่าช้าในสภาพแวดล้อมเครื่อง
- กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
คลิกแท็บเครือข่าย
คลิก NYAN ในแอปตัวอย่าง
โปรดทราบว่าไฟล์
nyan-nyan-module.js
จะปรากฏในแท็บเครือข่าย
ดูตัวอย่างนี้ใน GitHub
แสดงภาพหมุน
ขณะนี้เมื่อผู้ใช้คลิกปุ่ม NYAN แอปพลิเคชันไม่ได้ระบุว่ากำลังโหลด JavaScript ในเบื้องหลัง หากต้องการให้ผู้ใช้ทราบระหว่างที่โหลดสคริปต์ คุณอาจต้องเพิ่มตัวหมุน
โดยเริ่มต้นด้วยการเพิ่มมาร์กอัปสำหรับตัวบ่งชี้ภายในองค์ประกอบ router-outlet
ใน app.component.html
<router-outlet>
<span class="loader" *ngIf="loading"></span>
</router-outlet>
จากนั้นเพิ่มคลาส AppComponent
เพื่อจัดการการกำหนดเส้นทางเหตุการณ์ คลาสนี้จะตั้งค่า Flag loading
เป็น true
เมื่อได้ยินเหตุการณ์ RouteConfigLoadStart
และตั้งค่า Flag เป็น 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 โดยใช้การแยกโค้ดระดับเส้นทาง ดังนี้
- ใช้เครื่องมือสร้างโมดูลแบบโหลดล่าช้าของ Angular CLI เพื่อสร้างโครงสร้างพื้นฐานของเส้นทางที่โหลดแบบไดนามิกโดยอัตโนมัติ
- เพิ่มตัวบ่งชี้การโหลดเมื่อผู้ใช้ไปยังเส้นทางแบบ Lazy เพื่อแสดงว่ามีการดำเนินการต่อเนื่อง