Slide 1

Slide 1 text

DRYing out your client-side apps Sunday, February 12, 12

Slide 2

Slide 2 text

hello! ’ Garann (like Karen with a G) Means ’ Austin All-Girl Hack Night + Girl Develop It Austin ’ Node for Front-End Developers (O’Reilly) ’ [email protected] or @garannm Sunday, February 12, 12

Slide 3

Slide 3 text

so node is pretty great, right? Sunday, February 12, 12

Slide 4

Slide 4 text

and why? ’ fast! ’ evented! ’ super easy to set up! ’ awesome dev community! ’ reusable application code! Sunday, February 12, 12

Slide 5

Slide 5 text

maybe a little trickier ’ fast! ’ evented! ’ super easy to set up! ’ awesome dev community! ’ reusable application code! Sunday, February 12, 12

Slide 6

Slide 6 text

we never needed that before ’ client-side strictly presentational ’ DHTML ’ Ajax ’ explosion of JS libraries ’ client-side apps Sunday, February 12, 12

Slide 7

Slide 7 text

we never had anything to reuse* Sunday, February 12, 12

Slide 8

Slide 8 text

attempting reuse with a traditional server ’ server-side interpreters ’ compiled versions of logic for client ’ limited vocabulary that can be truly shared Sunday, February 12, 12

Slide 9

Slide 9 text

things we can reuse ’ models ’ views/templates ’ route patterns ’ external or third-party utilities Sunday, February 12, 12

Slide 10

Slide 10 text

caveats ’ essentially one way to import in node ’ modules have to check their context ’ may need to be both synchronous and asynchronous ’ user interaction has to be abstracted ’ no global scope on the server Sunday, February 12, 12

Slide 11

Slide 11 text

the whats Sunday, February 12, 12

Slide 12

Slide 12 text

models ’ easy-peasy! ’ sensible and simple to structure data same way ’ validation and rendering signatures can be the same ’ (even if functionality differs) Sunday, February 12, 12

Slide 13

Slide 13 text

models function Model( config ) { var that = { thing: config.thing, stuff: config.stuff || [] }; that.validate = function() { if ( that.stuff.length ) return true; } return that; } Sunday, February 12, 12

Slide 14

Slide 14 text

server socket.on( “modelUpdated”, function( data ) { var m = new Model( data ); if ( !m.validate() ) { socket.emit( “badData”, { message: “onoez” } ); } }); Sunday, February 12, 12

Slide 15

Slide 15 text

client btn.addEventListener( “click”, function() { var m = new Model({ thing: txtField.value, stuff: convenientlyDefinedArray }); if ( m.validate() ) { socket.emit ( “modelUpdated”, m ); } else { alert( “Oops - not enough stuff!” ); } }); Sunday, February 12, 12

Slide 16

Slide 16 text

templates ’ not all JS templates work client/server ’ all can be *made* to work client/server ’ used differently, loaded differently Sunday, February 12, 12

Slide 17

Slide 17 text

server ’ maximize size ’ minimize requests ’ child templates as dependencies ’ no need to cache ’ response has to wait for loading, compositing, rendering Sunday, February 12, 12

Slide 18

Slide 18 text

client ’ minimize size ’ minimize DOM interaction ’ swap out small bits of innerHTML ’ caching probably important ’ may be re-rendering constantly Sunday, February 12, 12

Slide 19

Slide 19 text

routes ’ generic functions or publish/subscribe ’ probably need to abstract input and output ’ RPC/RMI may substitute Sunday, February 12, 12

Slide 20

Slide 20 text

routes namespace.save = function( input, output ) { output.render ( “save”, input ); } Sunday, February 12, 12

Slide 21

Slide 21 text

server app.get( “/save”, function( req, res ) { routes.save( req.body, res ); }); Sunday, February 12, 12

Slide 22

Slide 22 text

client btn.addEventListener( “click”, function() { var formData = serializeData( “#myForm” ); routes.save( formData, myRenderer ); }); var myRenderer = function() { this.render = function( tmplName, data ) { document.querySelector( “#page” ).innerHTML = tmplEngine.template( tmplName, data ); }; }; Sunday, February 12, 12

Slide 23

Slide 23 text

alternatively.. namespace.save = function( input ) { pubsub.publish( “loadSave”, input ); }; Sunday, February 12, 12

Slide 24

Slide 24 text

utilities ’ client-side utils may rely on a global namespace ’ node modules probably expect exports ’ like templates, can be *made* to work bi-directionally Sunday, February 12, 12

Slide 25

Slide 25 text

the hows Sunday, February 12, 12

Slide 26

Slide 26 text

generally.. ’ files live on client ’ pretend you never heard of global scope ’ everything decoupled from DOM* ’ pass reference to anything with state Sunday, February 12, 12

Slide 27

Slide 27 text

1. create server-side DOM 2. ??? 3. profit Sunday, February 12, 12

Slide 28

Slide 28 text

server-side DOM ’ existing tools to create DOM in V8 ’ slow ’ server-side DOM rarely needed ’ for entire apps, almost never ’ have to replace or trigger user interactions Sunday, February 12, 12

Slide 29

Slide 29 text

perfect candidates ’ testing ’ spidering ’ scraping ’ anything that requires parsing markup Sunday, February 12, 12

Slide 30

Slide 30 text

WTF candidates ’ games ’ visual editors ’ anything where markup is merely the final representation ’ anything highly interactive Sunday, February 12, 12

Slide 31

Slide 31 text

where it gets used ’ templates ’ build up DOM with reference to elements (vs. string) ’ events “belong” to elements ’ existing client-side apps ’ quick n’ dirty Sunday, February 12, 12

Slide 32

Slide 32 text

write once, import twice Sunday, February 12, 12

Slide 33

Slide 33 text

require.js and r.js ’ node’s require is subtly different ’ formal dependency management solves namespace issue ’ kind of ’ text! prefix for loading unexecuted code Sunday, February 12, 12

Slide 34

Slide 34 text

server var requirejs = require( “requirejs” ); requirejs.config( { nodeRequire: require } ); requirejs( [“thing1”, “thing2”], function( t1, t2 ) { // whatever.. }); requirejs( [“text!public/template.html”], function( tmpl ) { // whatever (rendering version).. }); Sunday, February 12, 12

Slide 35

Slide 35 text

client requirejs( [“thing1”, “thing2”], function( t1, t2 ) { // whatever.. }); requirejs( [“text!public/template.html”], function( tmpl ) { // whatever (rendering version).. }); Sunday, February 12, 12

Slide 36

Slide 36 text

exports || namespace ’ everything in an IIFE ’ pass in scope ’ requires hard-coding client namespace Sunday, February 12, 12

Slide 37

Slide 37 text

exports || namespace (function( ns ) { ns.thing = function() { // whatever.. }; return ns; }( ( typeof process !== "undefined" && process.title === "node" ) ? exports : clientNamespace )); Sunday, February 12, 12

Slide 38

Slide 38 text

Remote procedure calls Sunday, February 12, 12

Slide 39

Slide 39 text

RPC/rmi ’ write code once to run in two places ’ both, not either ’ pass control with callbacks (which node needs anyway) Sunday, February 12, 12

Slide 40

Slide 40 text

server var dnode = require( “dnode” ); dnode( function( client, connection ) { this.biznessLogic = function() { // whatever.. } }).listen( 1337 ); Sunday, February 12, 12

Slide 41

Slide 41 text

client var dnode = require( “dnode” ); dnode.connect( function( remote ) { btn.addEventListener( “click”, function() { remote.biznessLogic(); }); }); Sunday, February 12, 12

Slide 42

Slide 42 text

end-to-end frameworks Sunday, February 12, 12

Slide 43

Slide 43 text

the future ’ assembling this stuff by hand is silly ’ reuse should be the default ’ room for many frameworks, many methodologies Sunday, February 12, 12

Slide 44

Slide 44 text

how would that look? ’ build step required? ’ framework creates server ’ server generates client-side assets from server code ’ controllers wrap RPC/RMI calls Sunday, February 12, 12

Slide 45

Slide 45 text

full-stack solutions ’ batman.js ’ derby.js ’ flatiron.js ’ thorax.js ’ drumkit.js ’ zomg: http://toolbox.no.de/categories/Frameworks Sunday, February 12, 12

Slide 46

Slide 46 text

changing everything ’ trying to do this since early 2000s, at least ’ and it’s sucked ’ browsers behaving more like servers ’ sockets, storage, I/O ’ and servers behaving more like browsers ’ \m/, JavaScript ,\m/ Sunday, February 12, 12

Slide 47

Slide 47 text

why the proliferation? ’ everyone coming to the same conclusion at once ’ different needs, but not really ’ different preferences ’ which fits your needs? Sunday, February 12, 12

Slide 48

Slide 48 text

lots of ways to share code ’ which pieces do you have? ’ which are crucial and which are “glue”? ’ e.g. templates may be unrelated to biz logic ’ are there constraints to how they’re handled? ’ e.g. maybe you can’t jump to a route/state by URL Sunday, February 12, 12

Slide 49

Slide 49 text

bottom line: Don’t repeat yourself ’ no reason to run logic on a different side than it’s used ’ no reason to duplicate code Sunday, February 12, 12

Slide 50

Slide 50 text

thanks! Sunday, February 12, 12

Slide 51

Slide 51 text

— image credits — ’ http://www.flickr.com/photos/breakfastcore/2285501111/ ’ http://www.flickr.com/photos/bondidwhat/6114903414/ ’ http://www.flickr.com/photos/rchappo2002/2694370462/ ’ http://www.flickr.com/photos/21233184@N02/4188316428/ ’ http://www.flickr.com/photos/blackcountrymuseums/5218004706/ ’ http://www.flickr.com/photos/catechism/3001280935/ ’ http://www.flickr.com/photos/murrus/2344711309/ ’ http://www.flickr.com/photos/carbonated/2105145079/ Sunday, February 12, 12