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

RequireJS - overview

RequireJS - overview

Nedeljko Damnjanovic

April 18, 2014
Tweet

More Decks by Nedeljko Damnjanovic

Other Decks in Programming

Transcript

  1. What, the heck is it, anyway? • RequireJS is a

    JavaScript file and module loader • RequireJS will improve the speed and quality of your code
  2. Not enough :/ Why should I use it? • You

    can create and re-use modules without polluting the global namespace • Async loading • You can structure your code • You can build for production • Web sites are turning into Web apps • Code complexity grows as the site gets bigger
  3. Hello World <!DOCTYPE html> <html> <head> <title>My Sample Project</title> <!--

    data-main attribute tells require.js to load scripts/main.js after require.js loads. --> <script data-main="scripts/main" src="scripts/require.js"></script> </head> <body> <h1>My Sample Project</h1> </body> </html> require(["helper/util"], function(util) { // This will load util.js //This function is called when //scripts/helper/util.js is loaded. //If util.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". });
  4. JS modules What are JavaScript modules? What is their purpose?

    • Definition: how to encapsulate a piece of code into a useful unit, and how to register its capability/export a value for the module. • Dependency References: how to refer to other units of code.
  5. JS today • Defined via an immediately executed factory function.

    • References to dependencies are done via global variable names that were loaded via an HTML script tag. • The dependencies are very weakly stated: the developer needs to know the right dependency order. For instance, The file containing Backbone cannot come before the jQuery tag. • It requires extra tooling to substitute a set of script tags into one tag for optimized deployment.
  6. Asynchronous Module Definition • The Asynchronous Module Definition (AMD) API

    specifies a mechanism for defining modules such that the module and its dependencies can be asynchronously loaded • Idea: write a bunch of script tags with implicit dependencies that you have to manually order • Register the factory function by calling define(), instead of immediately executing it. • Pass dependencies as an array of string values, do not grab globals. • Only execute the factory function once all the dependencies have been loaded and executed. //Calling define with a dependency array and a factory function define(['dep1', 'dep2'], function (dep1, dep2) { //Define the module value by returning a value. return function () {};
  7. data-main attribute • special attribute that require.js will check to

    start script loading • use a data-main script to set configuration options and then load the first application module Note: the script tag require.js generates for your data-main module includes the async attribute <script data-main="scripts/main" src="scripts/require.js"></script> <script src="scripts/other.js"></script> // contents of main.js: require.config({ paths: { foo: 'libs/foo-1.1.3' } }); // contents of other.js: // This code might be called before the require.config() in main.js // has executed. When that happens, require.js will attempt to // load 'scripts/foo.js' instead of 'scripts/libs/foo-1.1.3.js' require( ['foo'], function( foo ) { });
  8. baseUrl RequireJS loads all code relative to a baseUrl •

    baseUrl is normally set to the same directory as the script used in a data- main attribute for the top level script to load for a page • baseUrl can be set manually via the RequireJS config • There may be times when you do want to reference a script directly: • Ends in ".js". • Starts with a "/". • Contains an URL protocol, like "http:" or "https:".
  9. baseUrl - further notes • RequireJS also assumes by default

    that all dependencies are scripts => no ".js" suffix on module IDs. • With the paths config, you can set up locations of a group of scripts.
  10. best practice in index.html: <script data-main="js/app.js" src="js/require.js" ></script> requirejs.config({ //By

    default load any module IDs //from js/lib baseUrl: 'js/lib', //except, if the module ID starts //with "app", //load it from the js/app directory. //paths //config is relative to the baseUrl, //and //never includes a ".js" extension //since //the paths config could be for a directory. paths: { app: '../app' } });
  11. the module • well-scoped object that avoids polluting the global

    namespace • explicitly list its dependencies and get a handle on those dependencies - modules are loaded as fast as possible, even out of order, but evaluated in the correct dependency order - get dependencies as arguments
  12. the module - revealed • simple module, without dependecies //Inside

    file my/shirt.js: define({ color: "black", size: "unisize" });
  13. the module - revealed II //my/shirt.js now does setup work

    //before returning its module definition. define(function () { //Do setup work here return { color: "black", size: "unisize" } });
  14. the module - revealed III //my/shirt.js now has some dependencies,

    a cart and inventory //module in the same directory as shirt.js define(["./cart", "./inventory"], function(cart, inventory) { //return an object to define the "my/shirt" module. return { color: "blue", size: "large", addToCart: function() { inventory.decrement(this); cart.add(this); } } } );
  15. shim For older, traditional "browser globals" scripts that do not

    use define() to declare the dependencies and set a module value • configure the dependencies • exports • custom initialization
  16. shim II requirejs.config({ //Remember: only use shim config for non-AMD

    scripts, //scripts that do not already call define(). The shim //config will not work correctly if used on AMD scripts, //in particular, the exports and init config will not //be triggered, and the deps config will be confusing //for those cases. shim: { 'backbone': { //These script dependencies should be loaded before loading //backbone.js deps: ['underscore', 'jquery'], //Once loaded, use the global 'Backbone' as the //module value. exports: 'Backbone' }, //Then, later in a separate file, call it 'MyModel.js', a module is //defined, specifying 'backbone' as a dependency. RequireJS will use //the shim config to properly load 'backbone' and give a local //reference to this module. The global Backbone will still exist on //the page too. define(['backbone'], function (Backbone) { return Backbone.Model.extend({}); });
  17. maps For the given module prefix, instead of loading the

    module with the given ID, substitute a different module ID. requirejs.config({ map: { 'some/newmodule': { 'foo': 'foo1.2' }, 'some/oldmodule': { 'foo': 'foo1.0' } } });