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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Javascript first-class citizenery


Published on

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.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. JAVASCRIPT &1ST CLASS CITIZENRYFast, modular code with RequireJS &node.js
  • 2. 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:
  • 3. Agenda• Global Pollution• Dependencies & Modularisation• Building and Testing• Optimisation
  • 4. 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.
  • 5. Badness 1: Global functions<body> <button onclick="addMovie()">addMovie</button> <script type="text/javascript”> function addMovie() { $.observable( movies ).insert (; } </script></body>
  • 6. Badness 2: Well-known namespaces<html><head> <script src= … <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>
  • 7. Template Pattern(function($) { // nothing outside here can call this function function sumWithInterest( el, interset){ return $(el).val() * interest; } $.extend($.fn , sumWithInterest) // except …}(jQuery));
  • 8. RequireJs (module) patterndefine([“jquery”], function($) { function sumWithInterest( el, interest){ return $(el) .val() * interest; } return sumWithInterest// object or function});
  • 9. Dependencies & ModularisationLet‟s take that all a little bit more slowly.
  • 10. Each module ecapsulatesCreate Consumedefine(“main”, require(“main”) function(){ //all code in here // is scoped })
  • 11. Access in is via a return onlyCreate Consumedefine(“main”, require(“main”).init() function(){ return { init:function(){…} } })
  • 12. Dependencies are explicitdefine(“main”, [„log‟, „jquery‟], function( log, $ ){ log.debug( $(„body‟).text() ) })
  • 13. Module loading can be ordereddefine(“main”, [„log‟, „order!jquery‟, „order!jsrender‟], function( log, $ ){ $.template(„body‟).render() log.debug( $(„body‟).text() ) })
  • 14. Building & Testing
  • 15. Build command line• Rake• Gradle• Psake• Msbuild• Ant• Bat• sh
  • 16. Test-first via jasmineUnits• Views• EventsAcceptance• Full loading
  • 17. 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); }); }
  • 18. Test Eventsit("should register add order handler”, function() { _requires([“coffee/loader”])); spyOn(_, order).andCallThrough() _.orderHandler( $(#test), function(){ return {} ) $(#test).click() expect(_.order).toHaveBeenCalled() });
  • 19. 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++); });
  • 20. Build and get runtime errors$ rake buildnode lib/r.js -o 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)
  • 21. Throw away the debugger no break points or step through … no really, I‟m serious
  • 22. OptimisationWe still need to package code ready forserving. Why wait until run?
  • 23. Script-tag vomitIn development, it’s good Production, it’s not
  • 24. Pretty clean
  • 25. Create bundles & linted
  • 26. Script and CSS compressed
  • 27. Ready for deployment
  • 28. 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
  • 29. 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
  • 30. 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!
  • 31. Useful refs (and referred tomaterials)• requirejs.html••••••
  • 32. Good luck Todd Brackley twitter: toddbNZ code: