I’m using MVC4, why do I need Require.js? – or – Why is my JavaScript such a mess?

In the quest to create an elegant web interface using MVC, I had begun to add more and more JavaScript to my views.  Using great tools like jquery, Knockout, AJAX, modernizr, and underscore I began improving the interactivity and responsiveness of my web pages.  At first the UI code seemed fairly simple, and I even added it directly to the view (very bad practice).  However this made the page and JavaScript difficult to understand so I quickly began separating the JavaScript into a separate script file from the page.  Tip: It’s generally a good idea to minimize the number of programming languages used in a single file whenever possible.

Even after separating the Javascript into its own file, I still found it extremely unwieldy.  The code in the file covered vastly different and unrelated aspects of the page.  It also tightly coupled my JavaScript to the page and was not reusable.  As a C# developer who tries to follow the SOLID OO design principles, this type of low cohesion and tight coupling really felt wrong.

Next I tried to separate the code into multiple script files that were more logically organized.  Unfortunately this led me to even more issues:

  • How could I guarantee the JavaScript files were loaded in the right order?
  • How could I separate out different layers of the application and make sure that these layers could communicate effectively?
  • Why were these files so difficult to test?

I was really struggling with this design issue until I discovered AMD and began using Require.js.

JavaScript can get complicated quickly

Even on a simple web page, the Javascript necessary to create more elegant user interactions can quickly become complex.  It doesn’t take very long to have a copious number of event handlers, random functions, and code with low cohesion grouped into a single file.  This type of organization can make maintenance and understanding of this code extremely difficult and leads towards the proverbial “Spaghetti Code” effect.  A small change in one part of the code can cause cascading problems and unforeseen consequences in other parts of the file.

Unlike other higher-order languages (C#, Java, C++), JavaScript does not have constructs built into the environment or language to group code into cohesive loosely-coupled modules.  Because of this, much of the JavaScript seen in the wild today is not organized in a way which lends itself to maintainability or re-usability. 

Fortunately the development community has acknowledged these short-comings of the JavaScript language and begun to build tools and frameworks to address them.  There are several libraries and patterns which have been developed to assist us in better organizing our JavaScript code.  One of these libraries I have been using quite a bit lately is Require.js.

What is Require.js?

Require is a library which helps you effectively use the JavaScript Module Pattern (for a great description see Learning JavaScript Design Patterns by Addy Osmani)  by handling module definition, organization, and loading for you.  It utilizes the Asynchronous Module Definition (AMD) API.

For C# developers you can think of these modules as analogous to C# classes and their associated files.  Using Require.js allows you to break up your JavaScript code in much the same way C# allows you to break your code into classes so that you can follow SOLID design principles.  Require.js also resolves dependencies between these modules and loads them for your JavaScript application.   In this way it is also similar to a dependency injection framework in .NET.

Why should I use a module loader like Require.js?

The short answer: Require.js significantly improves JavaScript code organization.

It allows you to create small cohesive JavaScript modules and define the dependencies of those modules by passing them in as parameters.  Require takes care of finding and loading these dependencies for your modules through the use of path and file name conventions.  This gives you a great framework for re-factoring your JavaScript into small modules (individual files) that are much easier to understand and maintain.  As the code becomes more cohesive and loosely coupled it also becomes easier to test and more reliable.

Bundling and minifying with Require.js

ASP.NET MVC provides some really good out-of-the-box bundling and minification features.  These work very well and also include built-in cache busting capability through the use of tokens based on file changes.  However, remember that Require.js dynamically loads your module dependencies from the client via the AMD API.  Require.js has its own server side optimization script named r.js. 

R.js is a script that uses Uglify2 to minify / compress the JavaScript files and then it bundles them all together into a single file.  This process should be done during the build process and the built (minified and bundled) script file deployed with the application.  One of the issues that I ran into using R.js with MVC was dealing with client side file caching and use of a cache busting token.  I plan to cover the details of an MVC based solution for cache busting in a future blog post.  R.js is very easy to use and greatly improves the performance of pages using Require.js.

Conclusion

If you’ve been struggling with the organization and dependency management aspects of your JavaScript, then an AMD based loader like Require.js may be the perfect answer.  When you’re writing JavaScript code of any reasonable complexity it is extremely helpful to be able to  break it into small logical cohesive modules and to define and manage dependencies between these modules.  

4 thoughts on “I’m using MVC4, why do I need Require.js? – or – Why is my JavaScript such a mess?

  1. Thanks for the article. I’ve been looking to see if you can use MVC’s bundling/minification and require.js. Looks like using the r.js in our build process might be the way to go. You said ” I plan to cover the details of an MVC based solution for cache busting in a future blog post.” Any plans on writing that article :-). I’m interested in what you have to say about it. Thanks!

      1. Wondering if you ever got around to writing that blog post? Would love to see how your solution compares to what we ended up doing.

  2. I am also interested in how your MVC based solution turned out. I’ve been using grunt with config based on this example: https://github.com/asciidisco/grunt-requirejs/tree/master/examples/multipage

    It enables you to create a bundle per page in your build process. Its a bit cumbersome to handle this in the build process instead of in the development process (like MVC bundles).

    Its also important that you get non minified versions of your script when you are developing.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.