Slide 1

Slide 1 text

RequireJS A JavaScript Module Loader Greg Franko 1/30/2014

Slide 2

Slide 2 text

About The Speaker Greg Franko JavaScript Engineer at AddThis Open Source Developer Author Speaker

Slide 3

Slide 3 text

Why Do People Use RequireJS?

Slide 4

Slide 4 text

Performance Asynchronous and Dynamic Loading

Slide 5

Slide 5 text

Maintainability Decoupled Code into Modules

Slide 6

Slide 6 text

Workflow No Build Step Required

Slide 7

Slide 7 text

What Projects/Companies Use RequireJS?

Slide 8

Slide 8 text

jQuery Used in Development, Removed In Production

Slide 9

Slide 9 text

SoundCloud RequireJS in Development, AlmondJS In Production

Slide 10

Slide 10 text

PayPal Used In Both Development and Production

Slide 11

Slide 11 text

BBC News Used In Both Development and Production

Slide 12

Slide 12 text

AddThis RequireJS in Development, AMDCleanJS In Production

Slide 13

Slide 13 text

Are You Using RequireJS? It's Okay If You Aren't

Slide 14

Slide 14 text

RequireJS Basics Let's Learn

Slide 15

Slide 15 text

Most Projects Start Like This: JavaScript files are included as HTML script tags

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

This Is Better: Only Require.js is included as an HTML script tag data-main - Tells Require.js to load init.js first

Slide 18

Slide 18 text

Huh? init.js is getting loaded, but none of my other JavaScript files are RequireJS is the worst

Slide 19

Slide 19 text

Everything Will Be Okay! You haven't told RequireJS that init.js depends on jQuery, jQueryUI, Lodash, and Backbone

Slide 20

Slide 20 text

How Do I Tell RequireJS About My File Dependencies? By writing init.js in a format that Requirejs understands

Slide 21

Slide 21 text

What Format? AMD Asynchronous Module Definition

Slide 22

Slide 22 text

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 */ ;

Slide 23

Slide 23 text

Awesome, It Works! RequireJS Is The Best Please Tell Me More About AMD

Slide 24

Slide 24 text

AMD Module Format Used By RequireJS Exposes Two Global Methods: define() require()

Slide 25

Slide 25 text

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'; });

Slide 26

Slide 26 text

If define Is Confusing You... Let's See How It Would Look In Plain JavaScript var example = function() { return 'No dependencies, returns a string'; }();

Slide 27

Slide 27 text

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]; }; });

Slide 28

Slide 28 text

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);

Slide 29

Slide 29 text

Is That It? Nope, There Are Many Ways To Define an AMD Module Check Out More Module Definitions

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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.

Slide 32

Slide 32 text

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?

Slide 33

Slide 33 text

Third Party Libraries Cannot Assume AMD Is Being Used Can Still Provide Conditional Support

Slide 34

Slide 34 text

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; }); }

Slide 35

Slide 35 text

Third Party Examples

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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 _; }); }

Slide 38

Slide 38 text

Backbone Does Not Provide AMD Support yet // Backbone Source var Backbone; if (typeof exports !== 'undefined') { Backbone = exports; } else { Backbone = root.Backbone = {}; }

Slide 39

Slide 39 text

How Do You Use Scripts That Are Not AMD Compatible? Use the RequireJS Shim Configuration

Slide 40

Slide 40 text

Shim Configuration Useful for libraries that export a global variable requirejs.config({ shim: { 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' } } });

Slide 41

Slide 41 text

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)));

Slide 42

Slide 42 text

Shim Configuration Also Useful for Declaring Dependencies require.config({ shim: { 'jquery.ui.widget': ['jquery'], 'jquery.selectBoxIt': ['jquery.ui.widget'] } });

Slide 43

Slide 43 text

Hold Up Can You Explain The require.config() Method?

Slide 44

Slide 44 text

RequireJS Config RequireJS allows you to set application-level configuration options The configuration options should be set before you define/require any modules

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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...

Slide 47

Slide 47 text

Building with The RequireJS Optimizer

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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" }

Slide 50

Slide 50 text

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.

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

For A Complete Example, Check Out: Backbone-Require-Boilerplate

Slide 54

Slide 54 text

Additional Topics That May Interest You Browserify vs RequireJS Using CommonJS syntax with RequireJS ES6 Modules and The Future

Slide 55

Slide 55 text

Thanks! Twitter: GregFranko Github: gfranko