Javascript first-class citizenery
Upcoming SlideShare
Loading in...5
×
 

Javascript first-class citizenery

on

  • 1,639 views

Javascript and first-class citizenry: require.js & node.js...

Javascript and first-class citizenry: require.js & node.js

Javascript on web pages is ubiquitous and its problems are legendary. Javascript, seen as a second-class code citizen, is usually hacked together even by seasoned developers. New libraries (jQuery, prototype, backbone, knockout, underscore) and runtime tools (firebug, jasmine) look like they solve many problems - and they do. But they still leave poorly written code as just that. One key problem is that all javascript code lives globally and this results in poorly managed, tested and delivered code.

In this session, I will illustrate that we can treat javascript as a first-class citizen using with require.js and node.js: it can be modular, encapsulated and easily unit tested and added to continuous integration cycle. The dependencies between javascript modules can also be managed and packaged just like in C# and Java. In the end, we can resolve many javascript difficulties at compile time rather than waiting until runtime.

Statistics

Views

Total Views
1,639
Views on SlideShare
1,639
Embed Views
0

Actions

Likes
0
Downloads
20
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Javascript first-class citizenery Javascript first-class citizenery Presentation Transcript

  • JAVASCRIPT &1ST CLASS CITIZENRYFast, modular code with RequireJS &node.js talks@goneopen.com
  • Size and complexityAs JavaScript applications grow in size andcomplexity we need a real tool to handledependencies and keep our code modular.RequireJS give you an easy way to definedependencies on your module and itll makesure it‟s loaded before your code runs. It alsohas a nice build system which can be used tocompress and obfuscate your code using aclosure compiler. Adapted from: http://www.meetup.com/jQuery-Boston/events/16191792/
  • Agenda• Global Pollution• Dependencies & Modularisation• Building and Testing• Optimisation
  • Global PollutionIn Javascript, global functions are not agood strategy. They pollute. So, too do wellknown namespaces – but we‟ll live withthat. Modules provide a way forwardagainst these problems.
  • Badness 1: Global functions<body> <button onclick="addMovie()">addMovie</button> <script type="text/javascript”> function addMovie() { $.observable( movies ).insert (this.name); } </script></body>
  • Badness 2: Well-known namespaces<html><head> <script src=http://code.jquery.com/jquery.js … <script src="jsrender.js" type="text/javascript"></script></head><body> <div id="movieList"><b>Our Movies</b><br /></div> <script type="text/javascript”> $.templates({ movieTemplate: "#movieList” }) $.template.moveTemplate.render( ) </script></body></html>
  • Template Pattern(function($) { // nothing outside here can call this function function sumWithInterest( el, interset){ return $(el).val() * interest; } $.extend($.fn , sumWithInterest) // except …}(jQuery));
  • RequireJs (module) patterndefine([“jquery”], function($) { function sumWithInterest( el, interest){ return $(el) .val() * interest; } return sumWithInterest// object or function});
  • Dependencies & ModularisationLet‟s take that all a little bit more slowly.
  • Each module ecapsulatesCreate Consumedefine(“main”, require(“main”) function(){ //all code in here // is scoped })
  • Access in is via a return onlyCreate Consumedefine(“main”, require(“main”).init() function(){ return { init:function(){…} } })
  • Dependencies are explicitdefine(“main”, [„log‟, „jquery‟], function( log, $ ){ log.debug( $(„body‟).text() ) })
  • Module loading can be ordereddefine(“main”, [„log‟, „order!jquery‟, „order!jsrender‟], function( log, $ ){ $.template(„body‟).render() log.debug( $(„body‟).text() ) })
  • Building & Testing
  • Build command line• Rake• Gradle• Psake• Msbuild• Ant• Bat• sh
  • Test-first via jasmineUnits• Views• EventsAcceptance• Full loading
  • Test html Code template <li> <i>{{:type}}</i> (<abbr class="date”{{:ordered}}</abbr>) </li>Testdescribe("Html views", function() { var data = { type: "small", ordered: "1 min ago" } it("has a line item", function() { _requires(["text!coffee/views/_item.html", jsrender], function( text ){ $( "#test" ).html( $.templates( text ).render( data ) ); expect($("li", "#test" ).size()).toEqual(1); }); }
  • Test Eventsit("should register add order handler”, function() { _requires([“coffee/loader”])); spyOn(_, order).andCallThrough() _.orderHandler( $(#test), function(){ return {} ) $(#test).click() expect(_.order).toHaveBeenCalled() });
  • Test that it actually works! it("should be able to add new order", function(){ _requires(["coffee/main"])); val = $(li, ‟#orders).size(); $(button.order, ‟#orders).click()expect($(li, ‟#orders).size()).toEqual(val++); });
  • Build and get runtime errors$ rake buildnode lib/r.js -o app.build.jsTracing dependencies for: coffee/mainError: Error evaluating module "undefined" atlocation"/Users/todd/Documents/src/coffee/build/scripts/coffee/main.js":Unexpected token: punc (,) (line: 4, col: 16, pos:152)
  • Throw away the debugger no break points or step through … no really, I‟m serious
  • OptimisationWe still need to package code ready forserving. Why wait until run?
  • Script-tag vomitIn development, it’s good Production, it’s not
  • Pretty clean
  • Create bundles & linted
  • Script and CSS compressed
  • Ready for deployment
  • Gotchas!• File paths between development and production• CSS url paths• Text (html, json) loading without server• Creating a localhost server for text• Hassle for smaller projects
  • Follow-up areas• Different AMD implementations• Plugins (page load, internationalisation)• Lazy and dynamic loading• Wrapping non-AMD code• Coffeescript• Data-main loading• Build runners and CI integration
  • Finally, what does this mean?• We can unit test web-based application at the GUI layer• We CAN reduce the number of expensive, system tests (eg selenium)• Modularity and testing are likely to allow smaller pieces of work and potentially increased flow• All this (coupled with REST) means interesting times!
  • Useful refs (and referred tomaterials)• http://www.angrycoding.com/2011/09/managing-dependencies-with- requirejs.html• http://patrickmcelhaney.com/AMD-Talk/#microjs• http://projects.haykranen.nl/amsterdamjs• http://www.slideshare.net/JulienZee/parisjs-10-requirejs-9111799• http://www.slideshare.net/tim_doherty/requirejs-8858167• http://www.slideshare.net/timoxley/testable-client-sidemvcappsinjavascript• http://www.slideshare.net/sioked/requirejs
  • Good luck Todd Brackley goneopen.com twitter: toddbNZ code: github.com/toddb/javascript-amd