Theory
એને બહાર પાડવું, અને ઝડપી રાખવું
FestConnect નું front end તમારા machine પર ચાલે છે; હવે એ ખરા વપરાશકર્તાઓ માટે live થવું જોઈએ, અને events ની યાદી વધે તેમ પણ ઝડપી રહેવું જોઈએ. Front end નાં છેલ્લાં બે કૌશલ્યો એ જ છે: deployment (app ને build કરીને host કરવું) અને performance optimisation (Angular પાસે ઓછું કામ કરાવવું).
આ પાઠ production bundle બનાવવું, દરેક તબક્કાની ગોઠવણ માટે environments વાપરવાં, Firebase Hosting પર deploy કરવું, અને ત્રણ performance ની રીતો શીખવે છે: trackBy, OnPush change detection અને lazy loading. આટલાથી FestConnect બહાર પણ પડે છે અને ચપળ પણ રહે છે.
Theory
Build અને environments
Development દરમિયાન તમે ng serve ચલાવો છો, પણ બહાર પાડવા માટે તમારે build કરવું પડે: ng build --configuration production optimised bundle બનાવે છે, જે minified અને tree-shaken હોય છે (વણવપરાયેલો code કાઢી નાખેલો), અને એ host કરવા તૈયાર dist folder માં લખાય છે.
Apps ને જુદા જુદા તબક્કે જુદી ગોઠવણ પણ જોઈએ છે, દાખલા તરીકે તમારા laptop પર અને live server પર API નું URL જુદું હોય. Angular એ environment files વડે સંભાળે છે: development માટે environment.ts અને production માટે environment.prod.ts, અને build વખતે એમાંથી બરાબર વાળી ફાઇલ ગોઠવાઈ જાય છે. એટલે તમે code બદલ્યા વગર development નું API સ્થાનિક રાખી શકો છો અને production નું ખરા backend તરફ તકાવી શકો છો.
Practical
Build કરીને Firebase Hosting પર deploy કરવું
# Build an optimised production bundle into dist/
ng build --configuration production
# One-time setup, then deploy the built static files
firebase init hosting # point it at the dist/ output folder
firebase deploy # uploads and serves your app live
# Firebase Hosting serves the built files over HTTPS on a global CDN.Theory
ઝડપી રહેવાની ત્રણ રીત
FestConnect મોટું થાય તેમ ત્રણ રીતો એને ચપળ રાખે છે.
યાદીમાં (@for કે ngFor) વપરાતું trackBy Angular ને જણાવે છે કે દરેક item ને કઈ રીતે ઓળખવું, એટલે યાદી બદલાય ત્યારે એ દરેક row ફરી બનાવવાને બદલે ન બદલાયેલાં items નું DOM ફરી વાપરે છે. OnPush change detection component ને કહે છે કે ફક્ત એની @Input કિંમતો બદલાય ત્યારે જ ફરી તપાસ કરવી (બીજે ક્યાંક થતી દરેક નાની ઘટના વખતે નહીં), જેથી નકામું કામ ઘટે. Lazy loading (routing ના પાઠમાંથી) કોઈ page નો code એની મુલાકાત લેવાય ત્યાં સુધી લાવવાનું ટાળે છે, એટલે app વહેલું શરૂ થાય છે.
ત્રણેયનો ભાવ એક જ છે: ઓછું કામ કરો, અને ફક્ત જેને ખરેખર જરૂર હોય એને જ ફરી render કરો, ફરી તપાસો કે load કરો.
Practical
trackBy અને OnPush વાપરવાં
// OnPush: this component re-checks only when its @Input changes
@Component({
selector: 'app-events',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@for (e of events; track e.id) { <!-- 'track' is trackBy: reuse DOM -->
<app-event-card [event]="e" />
}`,
})
export class EventsComponent {
@Input() events: Event[] = [];
}
// track e.id lets Angular reuse rows whose id is unchanged, instead of all.Quiz
વારંવાર બદલાતી events ની લાંબી યાદીમાં trackBy (track e.id) ઉમેરવાથી શું સિદ્ધ થાય છે?
- એ યાદીને આપોઆપ ક્રમમાં ગોઠવી દે છે
- એ Angular ને આખી યાદી ફરી render કરવાને બદલે ન બદલાયેલાં items નું DOM ફરી વાપરવા દે છે, જેથી performance સુધરે છે
- એ યાદીના data ને encrypt કરે છે
- એ સરખા id વાળાં items ને કાઢી નાખે છે
Show the answer
એ Angular ને આખી યાદી ફરી render કરવાને બદલે ન બદલાયેલાં items નું DOM ફરી વાપરવા દે છે, જેથી performance સુધરે છે
trackBy Angular ને જણાવે છે કે દરેક item ને કઈ રીતે ઓળખવું (e.id વડે), એટલે યાદી બદલાય ત્યારે Angular દરેક row નાશ કરીને ફરી બનાવવાને બદલે જે items હજી એ જ છે એમનાં હાલનાં DOM elements ફરી વાપરી શકે છે અને ફક્ત ખરેખર બદલાયું હોય એને જ અડે છે. વિકલ્પ A ખોટો છે: trackBy ક્રમમાં ગોઠવતું નથી; એ ઓળખ પકડી રાખે છે. વિકલ્પ C ઉપજાવી કાઢેલો છે; એને encryption સાથે કશી લેવાદેવા નથી. વિકલ્પ D ખોટો છે: એ નકલી items કાઢી નાખતું નથી; એ તો id વડે updates દરમિયાન items ને મેળવે છે. trackBy વગર યાદી બદલાય ત્યારે દરેક row ફરી render થઈ શકે છે (લાંબી યાદીઓ માટે ધીમું); એની સાથે Angular ઓછામાં ઓછું કામ કરે છે. આ ઓછું કામ કરવાવાળી optimisation છે, જે આખા performance tuning નો સૂર છે.
Think first
OnPush change detection app ને ઝડપી કેમ બનાવે છે?
Angular તો components માં ફેરફાર આપોઆપ તપાસે જ છે. તો ઓછી વાર તપાસતું OnPush વસ્તુઓ બગાડવાને બદલે મદદ કેમ કરે છે? વિચારીને પછી tap કરો.
Show the answer
કારણ કે મૂળ ગોઠવણમાં Angular દરેક component ને બહુ વારંવાર ફરી તપાસે છે (app માં ક્યાંય પણ થતી લગભગ દરેક ઘટના પછી) કે view બદલવાની જરૂર છે કે નહીં, અને OnPush એ તપાસને સલામત રીતે ઘટાડીને ફક્ત component ના inputs ખરેખર બદલાય ત્યાં સુધી લાવી દે છે, એટલે app ઘણું ઓછું નકામું કામ કરે છે.
Change detection એ જ રીત છે જેનાથી Angular screen ને તમારા data સાથે મેળમાં રાખે છે: ઘટનાઓ પછી એ component ના વૃક્ષ પર ફરીને તપાસે છે કે template જે બતાવે છે એમાં કશું બદલાયું છે કે નહીં. મોટા app માં એનો અર્થ દરેક વપરાશ દીઠ હજારો તપાસ થઈ શકે, જેમાંથી મોટા ભાગનીને બદલવા જેવું કશું મળતું જ નથી, એટલે એ વેડફાયેલી મહેનત UI ને સુસ્ત બનાવી શકે છે.
OnPush Angular ને કહે છે: 'આ component નું view ફક્ત એની @Input કિંમતો પર (અને થોડાં સ્પષ્ટ કારણો પર) આધાર રાખે છે, એટલે એમાંનું કોઈ input નવો સંદર્ભ પકડે ત્યારે જ એને ફરી તપાસવાની જરૂર છે.' એનાથી Angular ઘણી change-detection ફેરીઓમાં એ component ને (અને ઘણી વાર એની નીચેની આખી શાખાને) તપાસવાનું છોડી શકે છે, જ્યાં એનાં inputs બદલાયાં જ ન હોય, અને કામ ખૂબ ઘટી જાય છે.
જ્યાં સુધી તમે એની રીત પાળો ત્યાં સુધી એનાથી ચોકસાઈ બગડતી નથી (data નીચે inputs દ્વારા મોકલો, inputs ને અપરિવર્તનીય ગણો, streams માટે observables કે async pipe વાપરો), અને smart તથા dumb components વાળી રચના એ રીતને કુદરતી રીતે ઉત્તેજે છે; સ્પષ્ટ inputs વાળાં dumb components OnPush માટે આદર્શ ઉમેદવાર છે.
એટલે OnPush ઝડપી છે કારણ કે એ 'બધું, બધો વખત તપાસો' ની જગ્યાએ 'આને ફક્ત એનાં inputs બદલાય ત્યારે તપાસો' મૂકે છે, અને view ને સાચું રાખીને પણ ઢગલાબંધ નકામી ગણતરી કાઢી નાખે છે. તપાસ ઓછી, પરિણામ એનું એ, અને app વધુ ઝડપી.
Summary
Key takeaways
- બહાર પાડવા માટે production bundle બનાવો: ng build --configuration production optimised (minified, tree-shaken) dist folder બનાવે છે.
- Environment files (environment.ts અને environment.prod.ts) API URL જેવી તબક્કાવાર ગોઠવણ રાખે છે, જે build વખતે બદલાઈ જાય છે.
- Firebase Hosting build થયેલી static files ને HTTPS પર પીરસે છે (firebase init hosting, firebase deploy).
- trackBy (track e.id) Angular ને આખી યાદી ફરી render કરવાને બદલે ન બદલાયેલાં items નું DOM ફરી વાપરવા દે છે.
- OnPush change detection component ને ફક્ત એની @Input કિંમતો બદલાય ત્યારે જ ફરી તપાસાવે છે, જેથી નકામું કામ ઘટે છે.
- Lazy loading કોઈ page નો code એની મુલાકાત લેવાય ત્યાં સુધી ટાળે છે; ત્રણેય optimisations નો એક જ વિચાર છે, ઓછું કામ કરવું.
- યાદ રાખવાની કડી: build કરીને Firebase પર deploy કરો; trackBy, OnPush અને lazy loading એને ઝડપી રાખે છે.