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

Modular JavaScript with require.js flavour

Modular JavaScript with require.js flavour

Avatar for Stefan Krätschmer

Stefan Krätschmer

July 26, 2012
Tweet

Other Decks in Programming

Transcript

  1. Reasons for not writing modules: it's a bad habit many

    files means many HTTP requests no dependency management in JavaScript* *not true
  2. <script src="module1.js"></script> <script src="module4.js"></script> <script src="module5.js"></script> <script src="module9.js"></script> <script src="module2.js"></script>

    <script src="module8.js"></script> <script src="module6.js"></script> <script src="module12.js"></script> <script src="module15.js"></script> ... That's what they are afraid of
  3. formerly ServerJS CommonJS · Unity · Specification “What I’m describing

    here is not a technical problem. It’s a matter of people getting together and making a decision to step forward and start building up something bigger and cooler together.” Kevin Dangoor
  4. Asynchronous Module Definition AMD define() require() “The AMD format comes

    from wanting a module format that was better than today's "write a bunch of script tags with implicit dependencies that you have to manually order" and something that was easy to use directly in the browser.” require.js documentation
  5. (function() { function private() {}; function public() {}; return {

    public: public }; })(); AMD uses module pattern
  6. define([ 'dep' ], function( dep ) { function private() {};

    function public() {}; return { public: public }; }); Module with dependencies
  7. ...and do a lot of other things with require. config

    baseUrl: paths: shim: map: config: waitSeconds: scriptcontext: deps: enforceDefine: urlArgs: ... the root path to use for all module lookups paths for module names not found under baseUrl dependencies and exports for not AMD scripts substitute a module ID passes configuration info to a module seconds to wait before giving up on loading a script allows require.js to load multiple versions of modules an array of dependencies to load throws an error if a script doesn't call define() query string args appended to URLs ...
  8. define([ 'dep' ], function( dep ) { // code var

    module = require( 'module' ); }); local require()
  9. define([ 'dep' ], function( dep ) { // code require([

    'module' ], function( module ) { module.doSomething(); }); }); require() again
  10. loads text files text! There are also css! and other

    plugins. You can write your own. text!path/filename.extension
  11. require([ 'text!templates/users.html' ], function( tplUsers ) { // ... var

    html = _.tempate( tplUsers, data ); $users.html( html ); // ... }); text! makes templating beautiful
  12. <% for ( var i = 0; i < users.length;

    i++ ) { %> <li> <a href="<%=users[ i ].url%>"> <%=users[ i ].name%> </a> </li> <% } %> users.html
  13. How we install plugins now <link rel="stylesheet" href="jquery-ui.css" media="all" />

    <link rel="stylesheet" href="ui.theme.css" media="all" /> <script src="jquery.min.js"></script> <script src="jquery-ui.min.js"></script> <script src="jquery.bgiframe-2.1.2.js"></script> <script src="jquery-ui-i18n.min.js"></script> jQuery UI
  14. Create a build script ({ appDir: "../", baseUrl: "./js", dir:

    "../build", paths: { text: "external/require/text" , jquery: "external/jquery-edge" }, modules: [ { name: "__core__" } ] }) folder that contains an app folder to save an output paths from require.config modules to optimize all dependencies will be included in a build file
  15. Mozilla & WebKit, minified scripts debug useSourceURL: true* JavaScript Source

    Map * do not use if IE conditional comments are turned on
  16. We can use shim require.config({ shim: { underscore: { exports:

    '_' }, backbone: { deps: [ 'underscore', 'jquery' ], exports: 'Backbone' }, 'external/jquery/ui': [ 'jquery' ] } }); exports a global variable defines dependencies and exports a global variable defines dependencies
  17. ...or we can just assume it's always there <script src="js/external/underscore.js"></script>

    <script src="js/external/backbone.js"></script> <script data-main="js/main" src="js/libs/require.js"></script>
  18. Requiring a module <script> require([ 'Maps/Google' ], function( GoogleMap )

    { GoogleMap.set({ center: 'London' , company: 'Google' }); }) </script>
  19. Defining 'config' module with empty config.js* <script> define( 'config', function()

    { return { testVar: 5 }); </script> *config.js is needed to prevent loading errors, see http://stackoverflow.com/questions/9916073/how- to-load-bootstrapped-models-in-backbone-js-while-using-amd-require-js/10288587#10288587
  20. Getting config define([ 'module' ], function( module ) { var

    config = module.config(); console.log( config.maxNews ); });
  21. define(function( require, exports, module ) { console.log( 'require: ', require

    ); console.log( 'exports: ', exports ); console.log( 'module: ', module ); }); Three require.js magic modules
  22. loads modules require Can also return a full path to

    the resource with .toUrl() require( 'moduleName' )
  23. information about a module module If you remember, we used

    module.config() to get settings module.id module.uri
  24. “Circular dependencies are rare, and usually a sign that you

    might want to rethink the design.” require.js documentation
  25. Use exports //inside b.js: define([ 'a', 'exports' ], function( a,

    exports ) { //If "a" has used exports, then we have a real //object reference here. However, we cannot use //any of a's properties until after b returns a value. exports.foo = function() { return a.bar(); }; });
  26. ...or require when needed define(function() { function foo() { //code

    require( ['a'], function( a ) { a.bar(); }); }; return { foo: foo }; });
  27. Harmony syntax example* module cakeFactory { // specify dependencies import

    baker from staff; export var oven = { makeCupcake: function( toppings ) { baker.bake( 'cupcake', toppings ); }; }; }; * by Addy Osmani
  28. · Uses new syntax · Cannot be shimmed in older

    browsers · Still in development · It would be easy to convert AMD to Harmony
  29. · Modules · Only one script tag · No global

    variables · Follows CommonJS specification · Dependencies · No need to worry about loading order · Makes it easier to manage js-templates · Optimization · Works in all browsers · Works with old scripts · Easy to implement and use