Slide 1

Slide 1 text

USING REQUIREJS WITH CAKEPHP Stephen Young @young_steveo Sr. Software Engineer - Zumba Fitness

Slide 2

Slide 2 text

WHAT'S THE POINT?

Slide 3

Slide 3 text

The Javascript layer of a typical MVC app starts simple. ...like a jQuery Zen garden. $ ( f u n c t i o n ( ) { / * a n i m a t e t h e b l o g t i t l e * / $ ( ' . t i t l e ' ) . s l i d e D o w n ( ) ; } ) ;

Slide 4

Slide 4 text

As the project matures, things get a little more tricky. $ ( f u n c t i o n ( ) { / * a n i m a t e t h e b l o g t i t l e * / $ ( ' . t i t l e ' ) . s l i d e D o w n ( 3 5 0 , f u n c t i o n ( ) { $ . g e t ( ' / s t a t s / c o u n t ' ) . d o n e ( f u n c t i o n ( d a t a ) { $ ( ' . s t a t s C o u n t ' ) . h t m l ( d a t a . c o u n t ) . a d d C l a s s ( ' g r e e n ' ) ; } ) ; } ) ; } ) ; Still maintainable... -ish

Slide 5

Slide 5 text

...before long

Slide 6

Slide 6 text

/ * m e g a _ f i l e . j s * / $ ( f u n c t i o n ( ) { i f ( w i n d o w . i s B l o g P a g e & & t y p e o f w i n d o w . A p p ! = = ' u n d e f i n e d ' ) { v a r a p p = n e w A p p ( ) ; / * a n i m a t e t h e b l o g t i t l e * / $ ( ' . t i t l e ' ) . s l i d e D o w n ( 3 5 0 , f u n c t i o n ( ) { $ . g e t ( ' / s t a t s / c o u n t ' ) . d o n e ( f u n c t i o n ( d a t a ) { $ ( ' . s t a t s C o u n t ' ) . h t m l ( d a t a . c o u n t ) . a d d C l a s s ( ' g r e e n ' ) ; $ . g e t S c r i p t ( ' / j s / s u p e r A w e s o m e P l u g i n ' , f u n c t i o n ( ) { $ . g e t ( ' / p o s t s / s o m e D a t a ' ) . d o n e ( f u n c t i o n ( d a t a ) { i f ( d a t a . p o s t s ) { d o S o m e C o o l S t u f f ( d a t a . p o s t s ) ; } } ) ; } ) ; } ) ; } ) ; } e l s e i f ( w i n d o w . i s C a t e g o r y ) { / * o h , g o d , p l e a s e , s t o p ! * /

Slide 7

Slide 7 text

Don't forget the layout file...

Slide 8

Slide 8 text

< s c r i p t s r c = " j s / b o x 2 d / c o m m o n / b 2 S e t t i n g s . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o m m o n / m a t h / b 2 V e c 2 . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o m m o n / m a t h / b 2 M a t 2 2 . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o m m o n / m a t h / b 2 M a t h . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 A A B B . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 B o u n d . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 B o u n d V a l u e s . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 P a i r . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 P a i r C a l l b a c k . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 B u f f e r e d P a i r . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 P a i r M a n a g e r . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 B r o a d P h a s e . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 C o l l i s i o n . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / F e a t u r e s . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 C o n t a c t I D . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 C o n t a c t P o i n t . j s " > < / s c r i p t > < s c r i p t s r c = " j s / b o x 2 d / c o l l i s i o n / b 2 D i s t a n c e . j s " > < / s c r i p t >

Slide 9

Slide 9 text

THERE IS A BETTER WAY.

Slide 10

Slide 10 text

WHAT IS REQUIREJS? javascript module & file loader AMD (asynchronous module definition) optimization tool http://requirejs.org

Slide 11

Slide 11 text

WHAT'S SO GREAT ABOUT AMD? Encapsulation Dependency Management

Slide 12

Slide 12 text

AMD EXAMPLE Define your modules: / * d e f i n e ( i d ? , d e p e n d e n c i e s ? , f a c t o r y ) ; * / d e f i n e ( " S o m e M o d u l e " , [ " d e p e n d e n c y " ] , f u n c t i o n ( d e p e n d e n c y ) { v a r S o m e M o d u l e = f u n c t i o n ( ) { } ; S o m e M o d u l e . p r o t o t y p e . i n i t = f u n c t i o n ( ) { d e p e n d e n c y . d o S t u f f ( ) ; } ; / * e t c . * / r e t u r n S o m e M o d u l e ; } ) ;

Slide 13

Slide 13 text

AMD EXAMPLE Load your modules and use them: / * r e q u i r e ( d e p e n d e n c i e s , c a l l b a c k ) ; * / r e q u i r e ( [ " M o d u l e A " , " M o d u l e B " ] , f u n c t i o n ( M o d u l e A , M o d u l e B ) { v a r m o d u l e = n e w M o d u l e A ( ) ; M o d u l e A . i n i t ( ) ; / * e t c . * / } ) ;

Slide 14

Slide 14 text

REQUIRE() OR DEFINE() ? Use `define` to declare a module for use elsewhere. Use `require` to pre-load dependencies and/or do some stuff.

Slide 15

Slide 15 text

WHAT IS CAKEPHP? (just kidding)

Slide 16

Slide 16 text

HELLO WORLD / * a p p / V i e w s / L a y o u t s / s o m e L a y o u t . c t p * / e c h o $ t h i s - > H t m l - > s c r i p t ( " r e q u i r e . j s " , [ " d a t a - m a i n " = > " / j s / b o o t s t r a p " ] ) ; / * a p p / w e b r o o t / j s / b o o t s t r a p . j s * / r e q u i r e j s . c o n f i g ( { p a t h s : { j q u e r y : ' j s / v e n d o r / j q u e r y . m i n ' } } ) ; r e q u i r e ( [ ' j s / l i b s / b l o g s ' ] ) ; / * a p p / w e b r o o t / j s / l i b s / b l o g s . j s * / r e q u i r e ( [ ' j q u e r y ' ] , f u n c t i o n ( $ ) { $ ( f u n c t i o n ( ) { / * e t c . * / } ) ; } ) ;

Slide 17

Slide 17 text

IT IS THAT SIMPLE. IS IT THAT SIMPLE? IT NEVER IS, IS IT? Even with RequireJS, things can get out of hand. As with many great tools, RequireJS gives you plenty of "rope."

Slide 18

Slide 18 text

TIPS Keep your modules focused; remember the single responsibility principle. Define a solid directory structure, and stick to it. (like your CakePHP /app directory) Think "automagic" and document your conventions. / j s / R E A D M E . m d

Slide 19

Slide 19 text

GOING BEYOND "HELLO WORLD" i.e. What if your project contains LOTS of javascript?

Slide 20

Slide 20 text

DISCLAIMER This works for us, and we like it, but feel free to tweak it to meet your needs.

Slide 21

Slide 21 text

IDENTIFY SECTIONS FOR YOUR PROJECT 1. Break the project down into sections, and create a module for each section (e.g. b l o g . j s , s h o p . j s , etc). 2. Identify any functionality that would be shared across multiple sections, and put them into common modules.

Slide 22

Slide 22 text

CHANGE THE LAYOUT BEFORE: / * ( d a t a - m a i n d o e s t h e h e a v y l i f t i n g ) * / e c h o $ t h i s - > H t m l - > s c r i p t ( " r e q u i r e . j s " , [ " d a t a - m a i n " = > " / j s / b o o t s t r a p " ] ) ; AFTER: / * n o m o r e d a t a - m a i n * / e c h o $ t h i s - > H t m l - > s c r i p t ( " r e q u i r e . j s " ) ; < s c r i p t > r e q u i r e ( [ ' / j s / b o o t s t r a p . j s ' ] , f u n c t i o n ( ) { r e q u i r e ( [ ' m o d u l e s / < ? p h p e c h o $ j a v a s c r i p t M o d u l e ; ? > ' ] ) ; } ) ; < / s c r i p t >

Slide 23

Slide 23 text

MODIFY THE APPCONTROLLER p u b l i c f u n c t i o n b e f o r e R e n d e r ( ) { $ t h i s - > s e t ( a r r a y ( ' j a v a s c r i p t M o d u l e ' = > $ t h i s - > j a v a s c r i p t M o d u l e ) ) ; } p u b l i c f u n c t i o n b e f o r e F i l t e r ( ) { / * j u s t a n i c e c o n v e n t i o n , y o u c o u l d u s e a d e f a u l t f i l e t o o * / i f ( ! $ t h i s - > j a v a s c r i p t M o d u l e ) { $ m o d u l e N a m e = I n f l e c t o r : : u n d e r s c o r e ( $ t h i s - > n a m e ) ; $ t h i s - > j a v a s c r i p t M o d u l e = $ m o d u l e N a m e ; } }

Slide 24

Slide 24 text

NEW BOOTSTRAP.JS FILE r e q u i r e j s . c o n f i g ( { p a t h s : { j q u e r y : ' j s / v e n d o r / j q u e r y ' , s o m e L i b : ' j s / l i b s / s o m e L i b ' , a n o t h e r L i b : ' j s / l i b s / a n o t h e r L i b ' } , s h i m : { a n o t h e r L i b : [ ' j q u e r y ' , ' s o m e L i b ' ] } } ) ;

Slide 25

Slide 25 text

OPTIMIZATION

Slide 26

Slide 26 text

R.JS RequireJS ships with a great minification/concatenation tool It runs in Node.js, Java with Rhino, or a browser It is configurable Bonus: it can minify CSS files for you too (but I'm not going to cover that today)

Slide 27

Slide 27 text

CONCATENATE DEPENDENCIES r.js will combine modules that are specified as dependencies in your module definitions

Slide 28

Slide 28 text

CONFIGURATION FILE { " m o d u l e s " : [ { " n a m e " : " b o o t s t r a p " , " i n c l u d e " : [ " u n d e r s c o r e " , " b a c k b o n e " , " j q u e r y " ] } , { " n a m e " : " b l o g s " , e x c l u d e : [ ' b o o t s t r a p ' ] } , { " n a m e " : " s h o p s " , e x c l u d e : [ ' b o o t s t r a p ' ] } , { " n a m e " : " p r o f i l e s " , e x c l u d e : [ ' b o o t s t r a p ' ] } , / * e t c . * /

Slide 29

Slide 29 text

THAT'S IT! QUESTIONS?

Slide 30

Slide 30 text

EXAMPLE REPO github.com/young-steveo/require_cake