Upgrade to Pro — share decks privately, control downloads, hide ads and more …

require.js

 require.js

Jason Lotito

March 28, 2013
Tweet

More Decks by Jason Lotito

Other Decks in Technology

Transcript

  1. why do I need it? • Web sites are turning

    into Web apps Wednesday, March 27, 13
  2. why do I need it? • Web sites are turning

    into Web apps • Code complexity grows as the site gets bigger Wednesday, March 27, 13
  3. why do I need it? • Web sites are turning

    into Web apps • Code complexity grows as the site gets bigger • Assembly gets harder Wednesday, March 27, 13
  4. why do I need it? • Web sites are turning

    into Web apps • Code complexity grows as the site gets bigger • Assembly gets harder • Developer wants discrete JS files/modules Wednesday, March 27, 13
  5. why do I need it? • Web sites are turning

    into Web apps • Code complexity grows as the site gets bigger • Assembly gets harder • Developer wants discrete JS files/modules • Deployment wants optimized code in just one or a few HTTP calls Wednesday, March 27, 13
  6. how does it solve this? • Some sort of #include/import/require

    • ability to load nested dependencies Wednesday, March 27, 13
  7. how does it solve this? • Some sort of #include/import/require

    • ability to load nested dependencies • ease of use for developer but then backed by an optimization tool that helps deployment Wednesday, March 27, 13
  8. how do I use require.js? // index.html <script data-main="scripts/main" src="scripts/require.js"></script>

    // scripts/main.js require(["loc/module"], function(module) { //This function is called when scripts/loc/module.js is loaded. //If module.js calls define(), then this function is not fired until //util's dependencies have loaded, and the util argument will hold //the module value for "helper/util". }); Wednesday, March 27, 13
  9. how do I use require.js? // index.html <script data-main="scripts/main" src="scripts/require.js"></script>

    // scripts/main.js require(["loc/module"], function(module) { //This function is called when scripts/loc/module.js is loaded. //If module.js calls define(), then this function is not fired until //util's dependencies have loaded, and the util argument will hold //the module value for "helper/util". }); Wednesday, March 27, 13
  10. how do I use require.js? // index.html <script data-main="scripts/main" src="scripts/require.js"></script>

    // scripts/main.js require(["loc/module"], function(module) { //This function is called when scripts/loc/module.js is loaded. //If module.js calls define(), then this function is not fired until //util's dependencies have loaded, and the util argument will hold //the module value for "helper/util". }); Wednesday, March 27, 13
  11. writing a module, today (function ($) { function Foo() {

    // do stuff here! } new Foo(); }(jQuery)); Wednesday, March 27, 13
  12. writing a module, today var $ = require('jquery'); exports.myExample =

    function () { // do stuff here! }; Wednesday, March 27, 13
  13. writing a module, today++: AMD define('mod',function(){ return function() { this.boom

    = function () { alert( 'Boom' ); }; } } ); Wednesday, March 27, 13
  14. why is this good? • Uses the CommonJS practice of

    string IDs for dependencies • IDs can be mapped to different paths. • Encapsulates the module definition. • Clear path to defining the module value. • Allows setting a function as a return value. Useful for constructor functions. • Defines a way to include multiple modules in one file. Wednesday, March 27, 13
  15. why is this good? • Easy to test, because modules

    are compartmentalized • Dependency Injection Wednesday, March 27, 13
  16. require still supports normal javascript require(["some/script.js"], function() { //This function

    is called after some/script.js has loaded. }); Wednesday, March 27, 13
  17. Optimization! • We can compile all requirements into one file

    • We can minimize CSS and JavaScript using Closure Compiler (or UglifyJS) • We aren’t worried about CSS today Wednesday, March 27, 13
  18. Can run... • In the browser • In Node •

    In Rhino Wednesday, March 27, 13
  19. Using Closure Compiler • Means uses Java • Means using

    Rhino • r.js Wednesday, March 27, 13
  20. What’s app.build.js ({ appDir: "../", baseUrl: "scripts/", dir: "../../webapp-build", optimize:

    "closure", paths: { "jquery": "empty:" }, modules: [ //Optimize the application files. jQuery is not //included since it is already in require-jquery.js { name: "main" } ], closure: { CompilerOptions: {}, CompilationLevel: 'SIMPLE_OPTIMIZATIONS', loggingLevel: 'WARNING' }, generateSourceMaps: true, preserveLicenseComments: false }) Wednesday, March 27, 13
  21. Alright stop... Let’s make sense of all these options by

    establishing our surroundings, namely, our project structure Wednesday, March 27, 13
  22. Our sample directory structure • r.js • webapp/ • app.html

    • scripts/ • app.build.js Wednesday, March 27, 13
  23. Our sample directory structure • r.js • webapp/ • app.html

    • scripts/ • app.build.js • app.build.dev.js Wednesday, March 27, 13
  24. Our sample directory structure • r.js • webapp/ • app.html

    • scripts/ • app.build.js • app.build.dev.js • main.js Wednesday, March 27, 13
  25. Our sample directory structure • r.js • webapp/ • app.html

    • scripts/ • app.build.js • app.build.dev.js • main.js • mod.js Wednesday, March 27, 13
  26. the app require( ["jquery", "mod"], function ( $, mod )

    { var mod = new mod(); setTimeout( function () { mod.boom(); $( 'h1' ).text( 'Hey you guys!' ); }, 2000 ); setTimeout( function () { mod.boom(); $( 'h1' ).text( 'Baby, ruth?' ); }, 4000 ); setTimeout( function () { mod.boom(); $( 'h1' ).text( 'Truffle Shuffle' ); }, 6000 ); } ); Wednesday, March 27, 13
  27. the module define('mod',function(){ return function() { this.boom = function ()

    { alert( 'Boom' ); }; } } ); Wednesday, March 27, 13
  28. modules can include other modules define('mod',['member/photos'],function(photos){ return function() { this.boom

    = function () { alert( 'Boom' ); photos.boom(); }; } } ); Wednesday, March 27, 13
  29. Compiled and minified via Closure Compiler (function(){define("mod",[],function(){return function(){this.boom=function() {alert("Boom")}}});require(["jquery","mod"],function(b,a){a=new a;setTimeout(function(){a.boom();b("h1").text("Hey

    you guys!")}, 2E3);setTimeout(function(){a.boom();b("h1").text("Baby, ruth?")}, 4E3);setTimeout(function(){a.boom();b("h1").text("Truffle Shuffle")}, 6E3)});define("main",function(){})})(); //@ sourceMappingURL=main.js.map Wednesday, March 27, 13
  30. Compiled with Source Maps closure: { CompilerOptions: {}, CompilationLevel: 'SIMPLE_OPTIMIZATIONS',

    loggingLevel: 'WARNING' }, generateSourceMaps: true, preserveLicenseComments: false Wednesday, March 27, 13
  31. .map file {"version":3, "file":"main.js", "lineCount":1, "mappings":"AAAC,SAAA,GACDA,MAAA,UAAgB,QAAA,SACP,SAAA,GACLC, SADK,CACOC,QAAAA,GAEVC,KAAA,QAFUD,CADP,CADO,CAAhB,CASA E,QAAA,kBAA4B,QAAA,CAAWC,CAAX,CAAcC,CAAd,EAEtBA,CAFsB,CAE hB,IAAIA,CAEdC,WAAA,CAAY,QAAA,GAEVD,CAAAL,KAAA,EACAI,EAAA, MAAAG,KAAA,iBAHU,CAAZ,KAMAD,WAAA,CAAY,QAAA,GAEVD,CAAAL,

    KAAA,EACAI,EAAA,MAAAG,KAAA,eAHU,CAAZ,KAMAD,WAAA,CAAY,QA AA,GAEVD,CAAAL,KAAA,EACAI,EAAA,MAAAG,KAAA,mBAHU,CAAZ,KAh B0B,CAA5B,CAwBAR,OAAA,QAAe,QAAA,IAAf,CAlCC,EAAA;", "sources":["main.js.src"], "names": ["define","boom","this.boom","alert","require","$","mod","setTimeout","text"]} Wednesday, March 27, 13
  32. testing define( 'mod', ['Profile'], function ( Profile ) { function

    mod() { this.boom = function () { return (new Profile()).mockTrueLol(); }; } return mod; } ); Wednesday, March 27, 13
  33. JSTestDriver # tests.jstd load: - r.js - webapp/tests/app.build.test.js # This

    let’s JSTestRunner serve up all the scripts for require serve: - webapp/scripts/*.js # Could also just do - webapp/tests/*.js test: - webapp/tests/GangTest.js - webapp/tests/LandTest.js - webapp/tests/ProfileTest.js - webapp/tests/TestJSTestDriver.js Wednesday, March 27, 13
  34. JSTestRunner # tests.jstd load: - r.js - webapp/tests/app.build.test.js # This

    let’s JSTestRunner serve up all the scripts for require serve: - webapp/scripts/*.js # Could also just do - webapp/tests/*.js test: - webapp/tests/GangTest.js - webapp/tests/LandTest.js - webapp/tests/ProfileTest.js - webapp/tests/TestJSTestDriver.js Wednesday, March 27, 13
  35. JSTestRunner # tests.jstd load: - r.js - webapp/tests/app.build.test.js # This

    let’s JSTestRunner serve up all the scripts for require serve: - webapp/scripts/*.js # Could also just do - webapp/tests/*.js test: - webapp/tests/GangTest.js - webapp/tests/LandTest.js - webapp/tests/ProfileTest.js - webapp/tests/TestJSTestDriver.js Wednesday, March 27, 13
  36. JSTestRunner # tests.jstd load: - r.js - webapp/tests/app.build.test.js # This

    let’s JSTestRunner serve up all the scripts for require serve: - webapp/scripts/*.js # Could also just do - webapp/tests/*.js test: - webapp/tests/GangTest.js - webapp/tests/LandTest.js - webapp/tests/ProfileTest.js - webapp/tests/TestJSTestDriver.js Wednesday, March 27, 13
  37. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  38. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  39. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  40. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  41. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  42. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  43. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { setUp: function

    ( queue ){ queue.call( function ( callbacks ){ require.undef( 'Profile' ); define( 'Profile', function (){ function Profile() {} Profile.prototype.mockTrueLol = function() { return true; }; return Profile; } ); require( [ 'mod' ], callbacks.add( function ( m ){ Mod = new m(); } ) ); } ); }, // tests here } ); })(); Wednesday, March 27, 13
  44. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { // setUp

    here tearDown: function (){ Mod = null; }, "test Mod is setup": function (){ assertTrue( Mod.hasOwnProperty( 'boom' ) ); assertTrue( Mod.boom() ); } } ); })(); Wednesday, March 27, 13
  45. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { // setUp

    here tearDown: function (){ Mod = null; }, "test Mod is setup": function (){ assertTrue( Mod.hasOwnProperty( 'boom' ) ); assertTrue( Mod.boom() ); } } ); })(); Wednesday, March 27, 13
  46. TestJSTestDriver (function (){ var Mod; AsyncTestCase( "TestJSTestDriver", { // setUp

    here tearDown: function (){ Mod = null; }, "test Mod is setup": function (){ assertTrue( Mod.hasOwnProperty( 'boom' ) ); assertTrue( Mod.boom() ); } } ); })(); // From Mod this.boom = function () { return (new Profile()).mockTrueLol(); }; Wednesday, March 27, 13