Modular Javascript Using Require
Modular Javascript Using Require
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
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
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
Related Research
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
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:
})();
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
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
return {
logThePair: function () {
alert("color: " + pair.color + ", size: " + pair.size);
}
};
});
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.
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
}
});
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
function reverseString(str) {
if(typeof str !== 'string') {
throw new Error('reverseString(str) accepts only strings.');
return;
}
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
RequireJs magically makes sure that this is not loaded until jQUery itself is loaded, at which poit
it will be provided to these plugins
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.
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:
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>
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)
Which we can then create a standard javascipt file such as the following
common) {
$(document).ready(function () {
$('#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.
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.
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.
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:
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):
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
This is what would be compiled (the JavaSript is on the right hand side) with the AMD
command line arg turned off.
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.
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.