Options Structuring the code: 1. Use globals and namespacing mishmash 2. AMD: Try to make node.js behave like the browser 3. Browserify: Try to make the browser behave like node.js
$() n p m i n s t a l l d o m r e a d y Total footprint: ~1700B r e q u i r e ( " d o m r e a d y " ) ( f u n c t i o n o n D o m R e a d y ( ) { / * . . . * / } ) ;
AJAX n p m i n s t a l l x h r ...or any of the other gazillion libs Total footprint: ~3.9k v a r x h r = r e q u i r e ( " x h r " ) x h r ( { b o d y : s o m e J S O N S t r i n g , u r i : " / f o o " , h e a d e r s : { " C o n t e n t - T y p e " : " a p p l i c a t i o n / j s o n " } } , f u n c t i o n ( e r r , r e s p , b o d y ) { / / r e s p = = = x h r / / c h e c k r e s p . b o d y o r r e s p . s t a t u s C o d e } )
Deferred Do not use even if you use jQuery! n p m i n s t a l l r s v p Total footprint: ~15kB (ouch) v a r x h r p = r e q u i r e ( ' r s v p ' ) . d e n o d e i f y ( r e q u i r e ( ' x h r ' ) ) ;
Manipulation v a r t o A r r a y = F u n c t i o n . p r o t o t y p e . c a l l . b i n d ( [ ] . s l i c e ) ; [ ] . s l i c e . c a l l ( n o d e L i s t ) ;
Traversing / Utilities ES5 Array methods (f o r E a c h ( ) , m a p ( ) et al) Watch Zakas' video: JS APIs you've never heard of Use l o d a s h if you have to
Attach an event handler to every element Not as expressive, but...: Less than 200B $ ( p a r e n t ) . f i n d ( s e l e c t o r ) . o n ( e v e n t , c a l l b a c k ) ; m o d u l e . e x p o r t s = f u n c t i o n ( p a r e n t , s e l e c t o r , e v e n t , c a l l b a c k ) { [ ] . f o r E a c h . c a l l ( p a r e n t . q u e r y S e l e c t o r A l l ( s e l e c t o r ) , f u n c t i o n ( e l ) { e l . a d d E v e n t L i s t e n e r ( e v e n t , c a l l b a c k , t r u e ) ; } ) ; } ;
grunt g r u n t . r e g i s t e r T a s k ( " t e s t " , [ " b r o w s e r i f y " , " _ c o p y - b u n d l e - t o - m i n " , " b u s t e r " ] ) ; g r u n t . r e g i s t e r T a s k ( " r e l e a s e " , [ " l e s s : d i s t " , " b r o w s e r i f y " , " u g l i f y " , " b u s t e r " ] ) ;
grunt-browserify src/index.js: b r o w s e r i f y : { d i s t : { f i l e s : { " b u i l d / b u n d l e . j s " : [ " s r c / i n d e x . j s " ] } , o p t i o n s : { t r a n s f o r m : [ " e s 6 i f y " , " e j s i f y " ] } } } v a r r s v p = r e q u i r e ( " r s v p " ) , m y M o d u l e = r e q u i r e ( " . / m y M o d u l e " ) ;
grunt-contrib-watch w a t c h : { s c r i p t s : { f i l e s : [ " * * / * . j s " , " * * / * . e j s " , " * * / * . j s o n " , " ! n o d e _ m o d u l e s / * * / * " ] , t a s k s : [ " t e s t " ] } , l e s s : { f i l e s : [ " * * / * . l e s s " ] , t a s k s : [ " l e s s : d e v " ] } }
Custom l o d a s h g r u n t . r e g i s t e r T a s k ( " l o d a s h i f y " , f u n c t i o n ( ) { v a r i n c l u d e s = [ " c l o n e " , " c o n t a i n s " , " e a c h " , " e x t e n d " , " f i l t e r " , " f o r E a c h " , " i s A r r a y " , " i s D a t e " , " i s O b j e c t " , " i s U n d e f i n e d " , " m a p " , " o b j e c t " , " p a i r s " , " p i c k " , " t o A r r a y " , " u n i q u e I d " ] ; r e q u i r e ( " s h e l l j s " ) . e x e c ( " . / n o d e _ m o d u l e s / . b i n / l o d a s h i n c l u d e = " + i n c l u d e s . j o i n ( " , " ) + " e x p o r t s = a m d - d - o b r o w s e r _ m o d u l e s / l o d a s h . j s " ) ; } ) ;
Templating: ejs n p m i n s t a l l e j s i f y index.ejs view.js < % v a r i 1 8 n = r e q u i r e ( " . / i 1 8 n " ) ; % > < p > < % - i 1 8 n . h e l l o % > , < % = n a m e % > < / p > r e q u i r e ( ' . / i n d e x . e j s ' ) ( { n a m e : " V i l n i u s J S " } ) ;
Use new stuff: es6ify Generators (yield), iterators, let, for..of, etc [ " o n e " , " t w o " ] . m a p ( ( i t e m ) = > " v a l u e : " + i t e m ) ;
Resources http://microjs.com/ http://caniuse.com/ ES5 compatibility tables (by @kangax) JavaScript APIs you've never heard of (by @slicknet) You're Missing the Point of Promises (by @domenic)