אפשר לשפר את ביצועי האפליקציה באמצעות פיצול קוד ברמת המסלול.
בפוסט הזה נסביר איך להגדיר פיצול קוד ברמת המסלול באפליקציה Angular. פיצול הקוד יכול לצמצם את גודל החבילה של JavaScript ולשפר משמעותית את זמן הפעילות.
דוגמאות הקוד מפורטות במאמר הזה ב-GitHub. הדוגמה למסלול eager זמינה בקטע eager branch. הדוגמה לפיצול הקוד ברמת המסלול היא ב-lazy branch.
למה פיצול קוד חשוב
המורכבות ההולכת וגדלה של יישומי אינטרנט הובילה לעלייה משמעותית בכמות של JavaScript שנשלח למשתמשים. קובצי JavaScript גדולים עלולים לעכב בצורה משמעותית את האינטראקטיביות, ולכן זה משאב יקר, במיוחד בנייד.
הדרך היעילה ביותר לכווץ חבילות JavaScript מבלי לוותר על תכונות באפליקציות שלך היא להציג פיצול קוד אגרסיבי.
פיצול קוד מאפשר לחלק את ה-JavaScript של האפליקציה למספר מקטעים המשויכים למסלולים או לתכונות שונים. גישה זו שולחת למשתמשים רק את ה-JavaScript הנחוץ להם במהלך הטעינה הראשונית של האפליקציה, תוך שמירה על זמני טעינה נמוכים.
טכניקות לפיצול קוד
ניתן לפצל את הקוד בשתי רמות: רמת הרכיב ורמת המסלול.
- בפיצול קוד ברמת הרכיב, אתם מעבירים רכיבים למקטעי JavaScript משלהם וטוענים אותם בצורה מושהית כשיש צורך בהם.
- בפיצול קוד ברמת המסלול, אונקלים את הפונקציונליות של כל מסלול בקטע נפרד. כשהמשתמשים מנווטים באפליקציה, הם מאחזרים את המקטעים המשויכים למסלולים השונים ומקבלים את הפונקציונליות המשויכת אליהם כשהם זקוקים לה.
הפוסט הזה מתמקד בהגדרת פיצול ברמת המסלול ב-Angular.
אפליקציה לדוגמה
לפני שנתעמק בשימוש בפיצול הקוד ברמת המסלול ב-Angular, נבחן אפליקציה לדוגמה:
בדוק את ההטמעה של המודולים של האפליקציה. בתוך AppModule
הוגדרו שני מסלולים: נתיב ברירת המחדל המשויך אל HomeComponent
ונתיב nyan
המשויך ל-NyanComponent
:
@NgModule({
...
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
pathMatch: 'full'
},
{
path: 'nyan',
component: NyanComponent
}
])
],
...
})
export class AppModule {}
פיצול קוד ברמת המסלול
כדי להגדיר פיצול קוד, צריך לארגן מחדש את נתיב Eeager של nyan
.
גרסה 8.1.0 של Angular CLI יכולה לעשות הכול בשבילכם באמצעות הפקודה הזו:
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)
}
יש שני הבדלים עיקריים בין מסלול הנסיעה המלאה:
- הגדרת
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 מוריד את 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
כדי לטפל בניתוב אירועים. המחלקה הזו תגדיר את הסימון 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 על ידי החלה של פיצול קוד ברמת המסלול:
- באמצעות מחולל המודולים של Angular CLI שנטענים באופן מדורג, תוכלו לגבש באופן אוטומטי מסלול שנטען באופן דינמי.
- אפשר להוסיף אינדיקטור לטעינה כשהמשתמש מנווט למסלול לא יציב כדי להראות שיש פעולה מתמשכת.