You are on page 1of 22

Sign up for our free weekly Web Developer Newsletter.

home articles quick answers discussions features community


Search for articles, questions, tips
help

Articles » Desktop Development » Miscellaneous » General Next

Article
Modular Javascript Using Require.Js About Article
Browse Code
By Sacha Barber, 2 Jul 2013
Bugs / Suggestions A look at creating well
5.00 (15 votes) Rate: structured modular
Stats javascript using AMD library
Revisions (2) Require.js
Download demo project : RequireJsDemos.zip Type Article
Alternatives

Comments (25) Introduction Licence CPOL

The Problem First Posted 2 Jul 2013


A Possible Solution Views 37,727
The Demos
Bookmarked 32 times
Simple Demo

Bootstrapping an app to use Require.js ASP Architect Dev


Using require() vs. define() Intermediate jQuery , +

Using With jQuery


View this article's
Using With ASP .NET MVC (4)
Workspace Using With TypeScript
Type Script Definition Files
Fork this Workspace
Use the AMD Module Command Line
Don't Use the AMD Module Command Line (CommonJS Style)

Connect using Git That's It Top News


Introduction China bans use of
Add your own Microsoft's Windows 8 on
alternative version I don't know how many of you use lots of JavaScript libraries, but we found ourselves using government computers
quite a lot within certain projects. One of the strange issues that came about from linking
JavaScript files was that we occasionally ran into dependency issues, where by a particular Get the Insider News free each
Share morning.
JavaScript source file would have a dependency on another JavaScript source file that was not
loaded (and therefore not available) yet.

As luck would have it there is an excellent library for dealing with interlinked JavaScript Related Videos
dependencies and module loading which is called : RequireJs

The Problem
You may be asking what problem RequireJs is attempting to solve. Well lets consider a most
common example, which is that of a custom jQuery plugin, where jQuery MUST be loaded
before the plugin will work. If we stuck to using standard script tags something like this

Collapse | Copy Code


<script src="scripts/myCooljqueryPlugins.js" type="text/javascript"></script>
<script src="scripts/jquery.js" type="text/javascript"></script>

We instantly have a problem, our custom jQuery plugins will not work, as jQuery itself has not
be loaded yet. Sure we could move the jQuery script tag to be before the custom jQuery Related Articles
plugins, which would indeed fix the problem this once. This is however a very isolated small use
Angular.js example application
case, which is not really the norm on large scale applications, where we may have many many
Making the most out of
related files which all have dependencies. This is where RequireJs can help. Want to know more,
JavaScript Intellisense in VS2012
read on.
#javascript Require.js vs
CommonJS / AMD modules
and #angularjs
Introduction to ASP.NET
Boilerplate
JavaScript Frameworks and
A Possible Solution Resources
Quick JavaScript OO (Object
So now that you know the problem what is a possible solution? Well as I have already stated Orientation) Primer

this article will use RequireJs a one viable solution to the problem just described. RequireJs does ElmahR = ELMAH + SignalR
a bit more than just solve dependencies, it also provides asynchronous module and file loaded. (1.0.0 released!)

In my mind the fact that RequireJs uses modules is a very good thing, as it gives a guiding Implementing RequireJs on
BackboneJs
push to the developer, which should nudge them into creating a module which has a single
responsibility which is never a bad thing. Using RequireJs we are able to specify things like: Case Study – Implementing an
HTML5/Javascript Enterprise
Java Application
Define a module
Require a module #javascript Require.js vs
CommonJS / AMD modules
The modules dependencies (via a RequireJs config called shim) and #angularjs
The module paths
RSA Interoperability between
JavaScript and
RSACryptoServiceProvider -
Form Login Example
Writing modular JavaScript
without polluting the global

The Demos namespace


Challenges and solutions -
Architecture of a Modern Web
This section will outline several different RequireJs examples, starting with a typical simple use Application - Part 1
case, and then building on to slightly more complex examples. Create String Variable from Text
File Source
Adding a Build Banner to
ASP.NET Pages

Simple Demo Chapter 5: Creating Web Widget


with HTML, CSS, and JavaScript
Getting Started with the
This is the simple basic 101 sample, and it illustrates the very basics of using RequireJs. This will RequireJS Library
be expanded upon later, but it does illustrate a few key points that we will come across in later Encryption - RSA implemented
examples. through Java Script to
Encryt/Decrypt data
Here is what the structure of this project looks like in Visual Studio: Performance Optimization of
ASP.NET Applications on
Client-side
ASP.NET MVC4: Bundling and
Minification

Related Research

Ten Tips of Web App Testing

Bootstrapping an app to use Require.js

One of the things you must do with RequireJs is to tell it which file will be used for the overall
configuration. Here is a simple example

Collapse | Copy Code Best Practices for Securing Your


<head> Private Keys and Code Signing
<title>My Sample Project</title> Certificates
<!-- 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>

You can see that the d ata-main attribute points to a main file which is what sets up the
RequireJs configuration. Lets see a simple example of this shall we:

Collapse | Copy Code


(function() { Essential Keys to Mobile
Usability
require(["app/data", "helper/util", "helper/logger"], function (data, util,
logger) {
//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".
alert('util module : ' + util.doubleItMethod(10));

//This function is called when scripts/app/data.js is loaded.


//If data.js calls define(), then this function is not fired until
//data's dependencies have loaded, and the util argument will hold
//the module value for "app/data".
alert('data module [0] : ' + data.storedData[0]);
alert('data module [1] : ' + data.storedData[1]);
How to Secure Your Software
logger.logThePair(); for the Mobile Apps Market
});

})();

What we can see there is the use of the req uire()function, which is what RequireJs gives us.
The 1st parameter (which may be an array as shown) specifies the dependencies that this
function has. Lets now focus our attention on one of those modules that we have a
dependency on.

This following snippet is the logger module, and note above how we state that we
require()the logger module, which RequireJs gives us, and then are free to use the modules
code. Which again can be seen above where we use the logger modules logTh ePair( )
function

Collapse | Copy Code


define(function (require) {
var pair = require(".././app/keyValuePairs");

return {
logThePair: function () {
alert("color: " + pair.color + ", size: " + pair.size);
}
};
});

In this example we define a module using define()and we also take in RequireJs which gets
special treatment, where RequireJs knows what to do with it. We are now able to use this
defined module using another r equire()call somewhere else, which we saw above when we
wrote out
Collapse | Copy Code
require(["app/data", "helper/util", "helper/logger"], function (data, util,
logger) {
....
}

One thing of note there is the path is also included "helper/logger" so require will look for a file
that matches that path and use that. We can also specify paths like this

Collapse | Copy Code


define(function (require) {
var pair = require(".././app/keyValuePairs");

return {
logThePair: function () {
alert("color: " + pair.color + ", size: " + pair.size);
}
};
});

We will see more on path configuration later

Using require () vs. define()

We can use both re quire()and define()to load module dependencies. The require()
function is used to run immediately, where as define()is used to define modules which may
be used from multiple locations.

Using With jQuery


So now that we have seen a trivial example of using RequireJs lets continue our journey. Lets
see what it takes to create an example where we have actually library depenencies, such as a
jQuery plugin that needs jQuery in order for function.

Here is what the structure of this project looks like in Visual Studio:

As before we start (as we always will) by telling RequireJs the main javascript code file to
boostrap the app

Collapse | Copy Code


<!DOCTYPE html>
<html>
<head>
<title>jQuery+RequireJS Sample Page</title>
<script data-main="scripts/app" src="scripts/lib/require.js"></script>
</head>
<body>
<h1>jQuery+RequireJS Sample Page</h1>
<input type="text" maxlength="150" id="txt" />
<input type="button" id="btn" value="click me" />
</body>
</html>

Where the scripts/app javascript file looks like this

Collapse | Copy Code


// Place third party dependencies in the lib folder
//
// Configure loading modules from the lib directory,
// except 'app' ones,
requirejs.config({
"baseUrl": "scripts/lib",
"paths": {
"app": "../app"
},
"shim": {
"jquery.appender": ["jquery"],
"jquery.textReplacer": ["jquery"],

}
});

// Load the main app module to start the app


requirejs(["app/main"]);

This time we can see something new. We can see that we are actually configuring RequireJs for
certain things, such as:

1. BaseUrl : Specifies the base path for all the scripts, you can still use RequireJs with relative
paths, but this is its base path
2. Paths : Is a map of named paths where we specify a well known name and a path
3. Shim : Is a map of files, and their dependecies. What this does is that is gives a hint to
RequireJs about the required module dependencies such that RequireJs will then know to
load them in the correct order. Remember that RequireJs uses a technique which means
modules are loaded asychronously. It can be seen from the example above that
"jquery.appender" and "jquery.textReplacer" are dependent on jQuery. As such RequireJs
will load that first.It may seem that we are just swapping the evils of having the correct
javascript imports in the html in the correct order for this, but what we do get from
RequireJs is that modules are loaded asychronously

The last point is that we then kick of the whole app by telling RequireJs wihch is the initial app
file that should be run. This is done using the line

Collapse | Copy Code


// Load the main app module to start the app
requirejs(["app/main"]);
So lets examine that file for a minute

Collapse | Copy Code


require(["jquery", "jquery.appender", "jquery.textReplacer"], function ($) {
//the jquery.appender.js plugin have been loaded.
$(function () {
$(document).ready(function () {
$('#btn').click(function () {
var old = $('#txt').val()
var rev = reverseString(old);
$('h1').replaceTextWithFade('Old text was : ' + old);
$('body').appendData(rev);
});
});
});

function reverseString(str) {
if(typeof str !== 'string') {
throw new Error('reverseString(str) accepts only strings.');
return;
}

var strArr = str.split('');


var reversed = strArr.reverse();
return reversed.join('');
};
});

It can be seen that is uses jQuery and the 2 custom jQuery plugins, that have by magic had
their dependency on jQuery satisfied by RequireJs, so we can now safely use them within the
javascript that asked for them as requirements.

Just for completeness here is one of the custom jQuery plugins that the code above makes use
of

Collapse | Copy Code


(function ($) {
$.fn.appendData = function (data) {
this.each(function () {
return this.append('<p>' + data + '</p>');
});
}
}(jQuery));

RequireJs magically makes sure that this is not loaded until jQUery itself is loaded, at which poit
it will be provided to these plugins

Using With ASP .NET MVC (4)


I also wanted to demonstrate how to use RequireJs within a ASP .NET MVC application (I chose
MVC 4). and here is how I did it.

Here is what the structure of this project looks like in Visual Studio:
I used the same boostrapper "app.js" code that we saw above, and the same 2 custom jQuery
plugins, that we just saw.

So now that you know are using some of the same stuff we just saw, lets proceed to the ASP
.NET MVC 4 specific bits shall we.

It starts with the Bundle.Config file which for me is as follows;

Collapse | Copy Code


public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/lib").Include(
"~/Scripts/Lib/require.js"));

bundles.Add(new
StyleBundle("~/Content/css").Include("~/Content/site.css"));
}
}

And then we have a master layout page which makes use of the bundles like this:

Collapse | Copy Code


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/lib")
<script type="text/javascript" src="~/Scripts/app.js"></script>
@RenderSection("scripts", required: false)
</head>
<body>
.....
.....
.....
</body>
</html>

However this time since we are relying on ASP .NET MVC 4s bundling capabilities we need to
provide a separate link to the boostrapper for RequireJs, which is done as follows:
Collapse | Copy Code
<script type="text/javascript" src="~/Scripts/app.js"></script>

Where app.jsis the same as the previous example.

From there all that is left to do is to declare what scripts you want per page (which is typical for
any ASP .NET MVC app)

Collapse | Copy Code


@{
ViewBag.Title = "Home Page";
}
....
....
....
....
@section Scripts {
<script src="~/Scripts/Controller/Home/Index.js"></script>
}
....
....
....
....

Which we can then create a standard javascipt file such as the following

Collapse | Copy Code


require(["jquery", "common/Utils", "jquery.appender", "jquery.textReplacer"],
function ($,

common) {

$(document).ready(function () {

$('#mainDiv').append('<p>Index page is working with Require.js</p>');


alert('Type some text into the text box and then click the button');

$('#btn').click(function () {
var old = $('#txt').val()
var rev = common.reverseString(old);
$('#appendToDiv').appendData(rev);
});
});
});
Which is specific for the controller/page combo and will be injected into the "Scripts" section of
the layout page.

Using With TypeScript


Typescript is the new kid on the block and is Microsofts attempt at proding OO like features to
JavaScript. Typescript essentially has its own compiler which take a Typescript file (*.ts) and
compiles that to a JavaScript file (*.js). I thought for completeness I should also cover
Typescript, though this only covers how to use RequireJs with Typescript.

Here is what the structure of this project looks like in Visual Studio:

Before we start I should mention that when working with Typescript you MOST definately want
to install the Web Essential Visual Studio Extension which makes working with Typescript so
much better. It provides a Typescript item template for Visual Studio. When the compilation
process is kicked off it will also create the JavaScript for the Typescript file as well.

Type Script Definition Files


One of the nice things about Typescript is that is will moan at save time (with the Web Essential
Visual Studio Extensions installed) if you do not have the appropriate definition files loaded.
Here is an example of that :

Click for larger image

Luckily help is at hand by way of the awesome set of definition files that are available for all the
major JavaScript libraries out there.

You just need to head over to the DefinitelyTyped web site which has definition files for
Typescript of all the major JavaScript libraries out there. Here is an example of what it looks like
with the correct definition files loaded, see how the compile errors have gone. Oh all I did was
include the correct definition files from the DefinitelyTyped web site and included them in the
the project and dragged them onto the Typescript file.
Click for larger image

There is one last thing that I wanted to mention when using Typescript and RequireJs together,
which is a command line argument that MUST be provided to work with RequireJs correctly.
This is the module type which can either be "commonJS" or "amd". "commonJS" would be used
if you were doing node development, whilst "amd" would be used when you are doing things
like RequireJs. By the way amd stands for "Asynchronous Module Definition".

There is a really nice article available here which has some more information avaiable on the
differences between "commonJS" and "amd" modular javascript:

http://addyosmani.com/writing-modular-js/
Luckily installing the eb Essential Visual Studio Extension makes things a lot easier for us, as all
we need to do is go set an Option in Visual Studio and the correct command line will be
emitted for us.

Anyway enough of all the background stuff, let's see some code shall we.

This is the raw html demo page

Collapse | Copy Code


<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">


<head>
<meta charset="utf-8" />
<title>TypeScript HTML App</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<script data-main="scripts/app" type="text/javascript"

src="scripts/lib/require.js"></script>
</head>
<body>
<h1 id="header">TypeScript HTML App</h1>
<div id="content" />
</body>
</html>

Where is can be seen that we use the same stuff as before where we link through to a
scripts/app bootstrapper file. This bootstrapping file is shown below. It is largely the same as
previous examples but we are of course able to make use of some of Typescripts features such
as lambdas ( () => ). You can click the image below to see a larger version of what JavaScript
gets created. Like I say it is largely the same as the previous examples:

Click for larger image

So now that we have a bootstrapper in place, lets look at the main app.js file.

I just wanted to show you the difference between what the Typescript compiler would do
depending on the command line option for picking your module type that we discussed earlier,
before we talk about the nitty gritty of using RequireJs (although if you just read the code
below, you can see it clearly):

Use the AMD Module Command Line

This is what would be compiled (the JavaSript is on the right hand side) with the AMD
command line arg turned on.
Click for larger image

Don't Use the AMD Module Command Line (CommonJS Style)

This is what would be compiled (the JavaSript is on the right hand side) with the AMD
command line arg turned off.

Click for larger image

See how its quite different. In fact using the "amd" command line argument causes the
Typescript compiler to actually use RequireJs syntax.

Anyway to use RequireJs inside of a Typescript file is pretty easy, all you have to do, is make
sure the Typescript file knows about the correct RequireJs definition file (which we talked about
earlier) and then start using RequireJs.

Here is small example:

Collapse | Copy Code


require(['jquery'], ($) => {
var el = $('#content');
var greeter = new gt.Greeter(el);
greeter.start();
});

I am using a vriation of the Gr eeterexample as shown on the Typescript web site, where we
simple update a DOM element. There is one thing to be aware of since I also wanted to use
jQuery to pick out the Htm lElement to pass to the Greeter you are then forced into using
the Typescript type a ny, as it does not recognize a jquery wrapped HtmlElement as a
HtmlElement type.

Anyway here is the code for the Greeter:

Click for larger image

You might also like