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

A Modular Workflow with Require.js

Greg Franko
January 30, 2014

A Modular Workflow with Require.js

Learn how and when to use Require.js, Almond.js, and AMDClean.js

Greg Franko

January 30, 2014
Tweet

More Decks by Greg Franko

Other Decks in Programming

Transcript

  1. Most Projects Start Like This: JavaScript files are included as

    HTML script tags <body> <script src='jquery.js'></script> <script src='jquery-ui.js'></script> <script src='lodash.js'></script> <script src='backbone.js'></script> <script src='init.js'></script> <script src='app.js'></script> </body>
  2. This Is Fine... If you don't have many dependencies If

    you don't care about page load performance If you don't like decoupled code
  3. This Is Better: Only Require.js is included as an HTML

    script tag <body> <script src='require.js' data-main='init'></script> </body> data-main - Tells Require.js to load init.js first
  4. Huh? init.js is getting loaded, but none of my other

    JavaScript files are RequireJS is the worst
  5. Everything Will Be Okay! You haven't told RequireJS that init.js

    depends on jQuery, jQueryUI, Lodash, and Backbone
  6. How Do I Tell RequireJS About My File Dependencies? By

    writing init.js in a format that Requirejs understands
  7. init.js AMD Example init.js Depends on jQuery, jQueryUI, Lodash, and

    Backbone fine(['jquery', 'jqueryui', 'lodash', 'backbone'], function($, null, _, Backbone) /* This function gets called after jquery.js, jqueryui.js, lodash.js, and backbone.js are loaded */ ;
  8. define(id?, dependencies?, factory) Communicates a File's Dependencies and Return Value

    Can return any type of value (e.g object, function, string) and defaults to undefined if no return value is specified. The module id and dependencies arguments are optional // example.js // Does not depend on any files and returns a string define(function() { return 'No dependencies, returns a string'; });
  9. If define Is Confusing You... Let's See How It Would

    Look In Plain JavaScript var example = function() { return 'No dependencies, returns a string'; }();
  10. define(id?, dependencies?, factory) Let's Look At A Slightly More Complicated

    Example // getUser.js // Depends on a file (users.js), and returns a getUser function define(['./users'], function(users) { return function getUser(username) { return users[username]; }; });
  11. If define Is Still Confusing... Let's See How It Would

    Look In Plain JavaScript var getUser = function(users) { return function getUser(username) { return users[username]; }; }(usersCollection);
  12. Is That It? Nope, There Are Many Ways To Define

    an AMD Module Check Out More Module Definitions
  13. require(Array, Function) Loads One Or More AMD Modules // Loads

    the example.js module from our first define() example require(['./example.js'], function(exampleText) { // Prints: 'example.js return value: No dependencies, returns a string' console.log('example.js return value: ', exampleText); }) That's All There Is To The require() Method
  14. Should I Use define or require? You Should Use Both

    Use define to wrap logic that you would like to re-use somewhere else in your application Use require when you just want a dependency to be loaded onto the page.
  15. Now What? Now That You Understand How To Create And

    Load AMD Modules... Let Me Answer Your Question With A Question Have You Ever Used JavaScript Code That You Didn't Write?
  16. How Would A Third Party Library Provide AMD Support? By

    Conditionally Wrapping Itself in a define method // If an AMD compatible loader is on the page if ( typeof define === "function" && define.amd ) { define([], function() { return exampleLib; }); }
  17. jQuery Provides AMD Support via a Named AMD module //

    jQuery Source if ( typeof define === "function" && define.amd ) { define( "jquery", [], function() { return jQuery; }); }
  18. Lodash Provides AMD Support via an Anonymous AMD module //

    Lodash Source if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) root._ = _; define(function() { return _; }); }
  19. Backbone Does Not Provide AMD Support yet // Backbone Source

    var Backbone; if (typeof exports !== 'undefined') { Backbone = exports; } else { Backbone = root.Backbone = {}; }
  20. How Do You Use Scripts That Are Not AMD Compatible?

    Use the RequireJS Shim Configuration
  21. Shim Configuration Useful for libraries that export a global variable

    requirejs.config({ shim: { 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' } } });
  22. Is This Black Magic? No, RequireJS just creates a define

    wrapper for all shimmed libraries define("backbone", ["underscore","jquery"], (function (global) { return function () { var ret, fn; return ret || global.Backbone; }; }(this)));
  23. Shim Configuration Also Useful for Declaring Dependencies require.config({ shim: {

    'jquery.ui.widget': ['jquery'], 'jquery.selectBoxIt': ['jquery.ui.widget'] } });
  24. RequireJS Config RequireJS allows you to set application-level configuration options

    The configuration options should be set before you define/require any modules
  25. Popular Config Options baseurl The beginning file path that is

    used for all of the file lookups paths Allows you to map module IDs to alias names (easier to type 'jquery' than '../../jquery') shim Allows you to make third-party libraries AMD compatible
  26. Let's Review Define() allows you to create AMD modules Require()

    allows you to load one or more AMD modules onto the page RequireJS configuration options provide flexibility and convenience Last but not least...
  27. The RequireJS Optimizer Node.js Command-Line Build Tool Concatenates Your AMD

    Project Into One File A Ton Of Options Can Be Used with Grunt or Gulp
  28. Example Build Profile { baseUrl: "public/js/", paths: { "desktop": "app/config/Init"

    }, optimize: "uglify", mainConfigFile: "public/js/app/config/Init.js", include: ["desktop"], out: "public/js/app/config/Init.min.js" }
  29. Common Optimizer Questions I thought RequireJS Didn't Require A Build

    Step? It doesn't, the optimizer is optional. Why Would I use the RequireJS Optimizer? If you want to build your project into one file Do I Still Need RequireJS After I Build? If you need to load any additional network resources with RequireJS, then yes. Otherwise, you may use Almond.js or AMDClean.js.
  30. Almond.js A Minimal (~400 line) RequireJS Replacement After Optimized Builds

    Does Not Allow Loading Network Resources Does Not Transform Source Code Example Build With Almond.js
  31. AMDClean.js An AMD Build Tool That Converts AMD Code To

    Standard JavaScript Allows You To Use AMD In Development Without Having To Include an AMD Library In Production Does Not Allow Loading Network Resources Transforms Source Code Example Build With AMDClean.js
  32. Additional Topics That May Interest You Browserify vs RequireJS Using

    CommonJS syntax with RequireJS ES6 Modules and The Future