Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

ANGULAR TUNING THE ENGINE

Slide 3

Slide 3 text

WHAT IS THIS TALK ABOUT? Angular event loop Understand the $digest cycle Performance tuning

Slide 4

Slide 4 text

ANGULAR EVENT LOOP

Slide 5

Slide 5 text

Browser

Slide 6

Slide 6 text

Browser Event Queue

Slide 7

Slide 7 text

Browser Event Queue click change focus

Slide 8

Slide 8 text

Browser Event Queue click change focus JavaScript

Slide 9

Slide 9 text

Browser Event Queue click change focus JavaScript Angular $apply(fn);

Slide 10

Slide 10 text

Browser Event Queue click change focus JavaScript Angular $apply(fn); fn();

Slide 11

Slide 11 text

Browser Event Queue click change focus JavaScript Angular $apply(fn); fn(); $digest

Slide 12

Slide 12 text

Browser Event Queue click change focus JavaScript Angular $apply(fn); fn(); $digest DOM Render

Slide 13

Slide 13 text

Input value:

Slide 14

Slide 14 text

< i n p u t n g - m o d e l = " t i t l e " > < d i v > I n p u t v a l u e : < s p a n > { { t i t l e } } < / s p a n > < / d i v >

Slide 15

Slide 15 text

$rootScope and $scopes $$watchers $scope.$watch $digest loop $DIGEST CYCLE

Slide 16

Slide 16 text

$ROOTSCOPE AND $SCOPES

Slide 17

Slide 17 text

$rootScope

Slide 18

Slide 18 text

$rootScope Parent $scope

Slide 19

Slide 19 text

$rootScope Parent $scope Child $scope Child $scope

Slide 20

Slide 20 text

$rootScope (ng-app) Parent $scope Child $scope Child $scope

Slide 21

Slide 21 text

$rootScope Parent $scope Child $scope (ng-app) (ng-controller) Child $scope

Slide 22

Slide 22 text

$rootScope Parent $scope Child $scope (ng-app) (ng-controller) Child $scope (ng-repeat) (ng-repeat)

Slide 23

Slide 23 text

THESE "SCOPES" ARE JUST OBJECTS THAT INHERIT FROM EACHOTHER

Slide 24

Slide 24 text

EACH "SCOPE" HAS A "$$WATCHERS" PROPERTY

Slide 25

Slide 25 text

$rootScope Parent $scope Child $scope $$watchers: null $$watchers: null Child $scope $$watchers: null $$watchers: null

Slide 26

Slide 26 text

$rootScope Parent $scope Child $scope $$watchers: null $$watchers: [{...}] Child $scope $$watchers: [{...}] $$watchers: [{...}]

Slide 27

Slide 27 text

S c o p e { $ $ w a t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { } , g e t : f u n c t i o n ( ) { } , l a s t : ' T o d d ' } ] }

Slide 28

Slide 28 text

$SCOPE.$WATCH

Slide 29

Slide 29 text

f u n c t i o n M a i n C o n t r o l l e r ( $ s c o p e ) { $ s c o p e . n a m e = ' T o d d ' ; $ s c o p e . $ w a t c h ( ' n a m e ' , f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { / / d o s o m e t h i n g w i t h n e w V a l u e } ) ; } a n g u l a r . m o d u l e ( ' a p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , M a i n C o n t r o l l e r ) ;

Slide 30

Slide 30 text

S c o p e { $ $ w a t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { } , g e t : f u n c t i o n ( ) { } , l a s t : ' T o d d ' } ] }

Slide 31

Slide 31 text

VIEW INTERPOLATION

Slide 32

Slide 32 text

f u n c t i o n M a i n C o n t r o l l e r ( $ s c o p e ) { $ s c o p e . n a m e = ' T o d d ' ; } a n g u l a r . m o d u l e ( ' a p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , M a i n C o n t r o l l e r ) ;

Slide 33

Slide 33 text

< ! - - T H I S c r e a t e s t h e " w a t c h e r " - - > < p > { { n a m e } } < / p >

Slide 34

Slide 34 text

S c o p e { $ $ w a t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { } , g e t : f u n c t i o n ( ) { } , l a s t : ' T o d d ' } ] }

Slide 35

Slide 35 text

WHY IS THIS IMPORTANT TO KNOW?

Slide 36

Slide 36 text

Angular uses $$watchers to update the DOM Angular uses $$watchers to sync our Model $$watchers impact performance $$WATCHERS ARE WHAT DRIVES ANGULAR

Slide 37

Slide 37 text

INPUT AND INTERPOLATION EXAMPLE

Slide 38

Slide 38 text

Input value:

Slide 39

Slide 39 text

< i n p u t n g - m o d e l = " t i t l e " > < d i v > I n p u t v a l u e : < s p a n > { { t i t l e } } < / s p a n > < / d i v >

Slide 40

Slide 40 text

NGMODEL INTERNALS v a r i n p u t = d o c u m e n t . q u e r y S e l e c t o r ( ' i n p u t ' ) ; i n p u t . a d d E v e n t L i s t e n e r ( ' i n p u t ' , f u n c t i o n ( ) { $ s c o p e . $ a p p l y ( f u n c t i o n ( ) { $ s c o p e . t i t l e = t h i s . v a l u e ; } ) ; } , f a l s e ) ;

Slide 41

Slide 41 text

NGMODEL CREATES A $$WATCHER $ s c o p e . $ w a t c h ( ' t i t l e ' , f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' i n p u t ' ) . v a l u e = n e w V a l u e ; } ) ; INTERPOLATION $$WATCHER $ s c o p e . $ w a t c h ( ' t i t l e ' , f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' s p a n ' ) . i n n e r H T M L = n e w V a l u e ; } ) ;

Slide 42

Slide 42 text

S c o p e { $ $ w a t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' i n p u t ' ) . v a l u e = n e w V a l u e ; } , g e t : f u n c t i o n ( ) { r e t u r n $ s c o p e . t i t l e ; } , l a s t : ' ' } , { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' s p a n ' ) . i n n e r H T M L = n e w V a l u e ; } , g e t : f u n c t i o n ( ) { r e t u r n $ s c o p e . t i t l e ; } , l a s t : ' ' } ] }

Slide 43

Slide 43 text

$digest cycle commences $scope.$apply is executed $scope.title is updated with input.value Angular app User types inside

Slide 44

Slide 44 text

Continues to next $$watcher until “clean ” If di erent, execute the “fn() ” property Re-runs $digest to ensure all $scopes are synced Compares the value to the “last ” property $digest loop Runs the “get() ” function to retrieve latest value

Slide 45

Slide 45 text

PERFORMANCE TUNING

Slide 46

Slide 46 text

PAIN POINT INTERPOLATION

Slide 47

Slide 47 text

Angular evaluates entire text content Potential DOM flicker (UX) INTERPOLATION

Slide 48

Slide 48 text

SOLUTION: CONSIDER NG-BIND < ! - - b e f o r e - - > < p > H e l l o { { n a m e } } a n d w e l c o m e t o F a c e b o o k ! < / p > < ! - - a f t e r - - > < p > H e l l o < s p a n n g - b i n d = " n a m e " > < / s p a n > a n d w e l c o m e t o F a c e b o o k ! < / p >

Slide 49

Slide 49 text

PAIN POINT NG-MODEL $DIGEST FREQUENCY

Slide 50

Slide 50 text

Change/input/etc events firing $digest per keystroke NG-MODEL $DIGEST FREQUENCY

Slide 51

Slide 51 text

SOLUTION: NGMODELOPTIONS < i n p u t t y p e = " t e x t " n g - m o d e l = " v m . m o d e l " n g - m o d e l - o p t i o n s = " { u p d a t e O n : ' d e f a u l t b l u r ' , d e b o u n c e : { ' d e f a u l t ' : 2 5 0 , ' b l u r ' : 0 } } " >

Slide 52

Slide 52 text

PAIN POINT SLOW NG-REPEAT

Slide 53

Slide 53 text

Stalls our application thread Bad end user experience Unresponsive/crashing SLOW NG-REPEAT

Slide 54

Slide 54 text

SOLUTION: ONE-TIME BINDINGS < u l > < l i n g - r e p e a t = " i t e m i n : : i t e m s " > { { i t e m } } < / l i > < / u l > < u l > < l i n g - r e p e a t = " i t e m i n i t e m s " > { { : : i t e m } } < / l i > < / u l >

Slide 55

Slide 55 text

PAIN POINT EXCESSIVE DOM RE-RENDERING

Slide 56

Slide 56 text

DOM rendering is expensive Huge DOM rendering is even more expensive We don't always need to re-render EXCESSIVE DOM RE-RENDERING

Slide 57

Slide 57 text

SOLUTION: TRACK BY < u l > < l i n g - r e p e a t = " i t e m i n i t e m s t r a c k b y i t e m . i d " > { { i t e m } } < / l i > < / u l >

Slide 58

Slide 58 text

PAIN POINT SLOW DOM FILTER PIPES

Slide 59

Slide 59 text

Filters run twice per $digest Huge collections equals slow filtering SLOW DOM FILTER PIPES

Slide 60

Slide 60 text

SOLUTION: CONTROLLER FILTERING f u n c t i o n M a i n C o n t r o l l e r ( $ f i l t e r ) { v a r c o l l e c t i o n = [ { . . . } ] ; t h i s . f i l t e r e d = c o l l e c t i o n ; t h i s . o n C l i c k = f u n c t i o n ( p r o p ) { / / D O M e q u i v a l e n t : c o l l e c t i o n | m y F i l t e r : p r o p t h i s . f i l t e r e d = $ f i l t e r ( ' m y F i l t e r ' ) ( c o l l e c t i o n , p r o p ) ; } } a n g u l a r . m o d u l e ( ' a p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , M a i n C o n t r o l l e r ) ;

Slide 61

Slide 61 text

PAIN POINT HTTP $DIGEST BATCHING

Slide 62

Slide 62 text

Multiple XHR's will each fire $digest HTTP $DIGEST BATCHING

Slide 63

Slide 63 text

SOLUTION: $HTTP + $APPLYASYNC f u n c t i o n c o n f i g ( $ h t t p P r o v i d e r ) { $ h t t p P r o v i d e r . u s e A p p l y A s y n c ( t r u e ) ; } a n g u l a r . m o d u l e ( ' a p p ' , [ ] ) . c o n f i g ( c o n f i g ) ;

Slide 64

Slide 64 text

PAIN POINT INTERNAL DI COMPILE SPEEDS

Slide 65

Slide 65 text

We expect too much from Angular INTERNAL DI COMPILE SPEEDS

Slide 66

Slide 66 text

SOLUTION: STRICT DI MODE / / u s a g e : < h t m l n g - s t r i c t - d i > f u n c t i o n S o m e S e r v i c e ( $ s c o p e , $ t i m e o u t ) { / / . . . } / / A r r a y a n n o t a t i o n s S o m e S e r v i c e . $ i n j e c t = [ ' $ s c o p e ' , ' $ t i m e o u t ' ] ; a n g u l a r . m o d u l e ( ' a p p ' ) / / I n l i n e a n n o t a t i o n s . f a c t o r y ( ' S o m e S e r v i c e ' , [ ' $ s c o p e ' , ' $ t i m e o u t ' , S o m e S e r v i c e ] ) ;

Slide 67

Slide 67 text

PAIN POINT NEEDLESS $$WATCHERS FROM DIRECTIVES

Slide 68

Slide 68 text

Choosing ng-if/ng-switch Choosing ng-show/ng-hide NEEDLESS $$WATCHERS FROM DIRECTIVES

Slide 69

Slide 69 text

SOLUTION: UNDERSTANDING < ! - - n g - i f / n g - s w i t c h - - > < u l n g - i f = " v m . e x p o s e N a v " > < l i n g - r e p e a t = " m e n u i n v m . m e n u s " > < / l i > < / u l > < ! - - n g - s h o w / n g - h i d e - - > < u l n g - s h o w = " v m . e x p o s e N a v " > < l i n g - r e p e a t = " m e n u i n v m . m e n u s " > < / l i > < / u l >

Slide 70

Slide 70 text

PAIN POINT EXTRA DOM QUERYING/PROCESSING

Slide 71

Slide 71 text

Internal .data() calls for binding info Class name additions EXTRA DOM QUERYING/PROCESSING

Slide 72

Slide 72 text

SOLUTION: DISABLE DEBUG INFO f u n c t i o n c o n f i g ( $ c o m p i l e P r o v i d e r ) { $ c o m p i l e P r o v i d e r . d e b u g I n f o E n a b l e d ( f a l s e ) ; } a n g u l a r . m o d u l e ( ' a p p ' , [ ] ) . c o n f i g ( c o n f i g ) ;

Slide 73

Slide 73 text

SOLUTION: DISABLE DEBUG INFO < ! - - e n a b l e d - - > < d i v n g - c o n t r o l l e r = " M a i n C t r l a s v m " c l a s s = " n g - s c o p e n g - b i n d i n g " > < m y - d i r e c t i v e c l a s s = " n g - i s o l a t e - s c o p e " > < / m y - d i r e c t i v e > < / d i v > < ! - - d i s a b l e d - - > < d i v n g - c o n t r o l l e r = " M a i n C t r l a s v m " > < m y - d i r e c t i v e > < / m y - d i r e c t i v e > < / d i v >

Slide 74

Slide 74 text

THAT'S ALL FOLKS! UNTIL NEXT TIME :)