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

Modular JavaScript with require.js flavour

Modular JavaScript with require.js flavour

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