Next Generation JavaScript with AMD and RequireJS: New on Premium
plusvideos

Next Generation JavaScript with AMD and RequireJS: New on Premium

Tutorial Details
  • Topics Covered: RequireJS
  • Format: Written and 1hr Video

I don’t know about you, but I’m always looking for better ways to organize my JavaScript. Recently (only a week or so ago), I’ve discovered what seems to be the best pattern yet. In this tutorial, I’ll introduce you to AMD: Asynchronous Module Definition and RequireJS. Hang on tight; it’ll be a wild ride!

Become a Premium member to read this tutorial/screencast, as well as hundreds of other advanced tutorials and screencasts from the Tuts+ network.


The Problem

If you’ve been writing client-side JavaScript for a while, you might have noticed a <sarcasm> small </sarcasm> problem with JavaScript. The only—or at least, the standard—way of getting multiple JavaScript files onto a page is to include multiple script tags:

<script src="file1.js"></script>
<script src="file2.js"></script>
<script src="file3.js"></script>

There are a couple of issues with this method.

Firstly, it’s just plain inconvenient. All the JavaScript in all the scripts is loaded into the global “namespace.” Of course, this may be misleading to beginners, who could easily—and excusable—think that identically-named variables in different files won’t conflict. But more than that, it’s a pain for experienced JavaScript developers with perhaps dozens of JavaScript files. Some files will depend on others, which may depend on others, etc. And you’re on playground duty: you’ve got to make sure they all arrive in the right order, and that nobody clobbers anybody. This can be both tricky or time-consuming, depending on the project.

Secondly—and more importantly—when a browser is downloading and executing JavaScript files, that’s all it’s doing; it’s blocking the downloading of other content until that’s done. This is why you’ve heard it recommended to put your <script> tags at the end of your <body>, instead of in your <head> as used to be the idea: that way, all your other content (HTML, CSS, images, etc.) will be visible to the user before the JavaScript is downloaded and executed. By using one of the many script loaders available, you’ll be able optimize this process at much as possible. RequireJS is one of those loaders, and you’ll get all the benefits of using it with AMD. For more on this, read the first chapter (and of course all the rest!) of High Performance JavaScript by Nicolas C. Zakas.

But all these script loaders—and all the other Javascript libraries and frameworks—cause a third problem that may not seem like a problem, but really is. You can (and should) read Stoyan Stefanov’s book JavaScript Patterns and get all kinds of great ideas for good coding patterns, or use frameworks like Dojo or Mootools that support great methods of modularization, etc. These patterns are a dime a dozen. However, they’re all different. In her talk “Modern JavaScript” at JSConf 2011, Rebecca Murphey said that she would love a JavaScript world where you could pick and choose where you get your functionality: you could get your DOM manipulation from jQuery, your array utilities from YUI, your UI widgets from Dojo, etc. Trying this today would be a nightmare. But, guess what? AMD solves this. We’ll see how.


Join Net Premium to Continue Reading…

NETTUTS+ Screencasts and Bonus Tutorials

For those unfamiliar, the family of Tuts+ sites runs a premium membership service. For $19 per month, you gain access to exclusive premium tutorials, screencasts, and freebies from Nettuts+, Psdtuts+, Aetuts+, Audiotuts+, Vectortuts+, and CgTuts+ For the price of a pizza, you’ll learn from some of the best minds in the business. Become a Premium member to read this tutorial, as well as hundreds of other advanced tutorials and screencasts.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Daniel

    If it wasnt for that i made my own CodeIgniter library that concats, minifiy and gzip my JS/CSS, i would use this.

    its also handy to have a php parser doing it when bumping up the revision, due to variables in css/js!

    • http://aryweb.nl Arian

      You can concatenate the files with the requirejs optimizer (http://requirejs.org/docs/optimization.html) or use a in PHP written packager (https://github.com/arian/amd-packager-php) which can concatenate your files as well and includes a small define() function to bootstrap your application.

      The PHP packager could possibly integrate with the CodeIgniter framework, only thing which has to be taken care of is caching of course. After the concatenation you could add another compression step.

  • Andrea

    First time I read the title, I thought that AMD put some new extension on their upcoming processor for javascript acceleration.. LOL

    • http://www.umarjadoon.com Umar

      Haha, I had the exact same thought! =P

      • Andrea

        So this means that we are geeks ;P

  • Dhruv Kumar

    Yes, but kinda stupid geeks…

  • David

    Doesn’t Nicholas Zakas not recommend using script loaders because they all rely on browser detection, or have things changed since that article?

    http://www.nczonline.net/blog/2010/12/21/thoughts-on-script-loaders/

    • http://www.nczonline.net/ Nicholas C. Zakas

      My advice hasn’t changed.

    • http://requirejs.org James Burke

      The overall goal for RequireJS, and more generally the AMD module format, is to point the way to modular JavaScript. Script loading is a means to that goal, but not the main goal. As usual, the use of an optimization tool (like the RequireJS optimizer) to concatenate scripts together is recommended for deployment. With the Almond mini-AMD shim, RequireJS does not need to be shipped in the deployed site, and what is considered a script loader can be avoided outside of development.

      All that said, being able to dynamically load scripts after initial page load is useful for some sites, and RequireJS can help with that too, while still promoting modular scripts with explicit dependencies.

      Disclaimer: I’m the main developer of RequireJS, but I have not watched this tutorial.

  • http://mastrotek.com web design new york

    Great stuff. But arent script loaders a no-no

  • Barry

    Will RequireJS also work in offline mode? if not, i will not use this at all.

  • lukins

    Andrew, thank you for another great tut!
    I have one question, an example you used in screencast has only one page, so you just concated&minifyied all the js files (required by main.js) for that page in one file. What if you would have more pages that require different js files, would you still concate&minify all of them into one file for the whole website or would you create combined files for each page?
    To be more clear, lets assume you are using dom/events.js and utils/array.js in you website.
    page 1.html loads main1.js that depends on dom/events.js and 2.html loads main2.js that depends on utils/array.js
    Ideally, 1.html should load require.js and combined.js that contains main1.js+dom/events.js and 2.html should load require.js and combined.js that contains main2.js+utils/events.js and that would be just fine for separate examples. But what happens when we are talking about these files as about parts of one website, is it more practical to have combined files for each page or ONE huge mammoth that combines all the dependencies?

  • http://andrewburgess.ca Andrew Burgess
    Author

    Thanks for the comments, everyone! I’ve been away and offline for a couple of days, so I haven’t had a chance to follow-up until now.

    @David: My thanks to Nicolas and James for stepping in here and answering. I don’t think I can add anything, other than that I think using RequireJS in development and an AMD-shim in production is a solid way to work. And like James said, the script loading isn’t necessary when using AMD. That’s important to remember.

    @Barry: I’m not sure what you mean by “offline.” If you mean with an HTML5 app cache, I’m not sure. As I said above, I think using a mini AMD lib (like Almond) would be the best production idea, and that would work fine with an app cache, AFAIK.

    @lukins: hmm, good question. I think I would probably do something with excluding repeatedly used modules from all but one file when using the optimization tool. This will work, because once the module is loaded into the browser’s JS environment, it will work across all JS files.

    Hope that helps! Feel free to post any other questions :)

    • lukins

      Sorry, I’m not sure I could understand you. Did you mean you would merge all repeatedly used modules in one file and all others in other files? I would be very glad if you could rephrase your sentence. Thanks

      • http://andrewburgess.ca Andrew Burgess
        Author

        Re-reading your original question, I’m realizing that I misunderstood it. Sorry about that! :)

        In the case you outlined, I would probably have two separate JS files for the two pages; that way, you’re never loading more code than you need to.

      • lukins

        Hi Andrew,
        Thanks for reply!
        Right, that way you are never loading more code than need to, and it’s great imho, but from another point of view, you are doing more HTTP requests (assuming you will definitely visit both pages). If you would have one big file containing modules used by both pages, it would be already cached by browser after visiting first page.
        Now, if we take this example a little further, and, let’s say, scale our project up to 100 pages with similar dependencies pattern – there are total of 20 modules, 15 are being used by multiple pages, while each one of the remaining 5 is being used by one unique page. How would you concat&compress files then?
        If you would ask me, I would say that I don’t know which way is the best. But I can see three options so far:
        1) to concat all modules in one big file
        2) to generate 100 js files that contain minimum required code for each page
        3) to find a “Golden Mean”, which by its definition is not defined, so we can split it into even more options, the first one I can think of is: to concat 15 modules into one file and to leave remaining 5 in separate files.
        So, as for an example with most HTTP requests, if we are visiting page that requires one of “15″ and one of “5″, it would load “require.js”, “combined_15_modules.js” and script that contains only one of 5 modules, the one page requires.
        I would use option #3, what about you?

      • http://andrewburgess.ca Andrew Burgess
        Author

        Having never worked on a site that large, I’m really not sure. I haven’t thought a whole lot about this, but at first blush, I think your example may be somewhat unrealistic. I say this because I’m thinking that a web app that is this JavaScript-heavy will probably not have so many pages; there’s a pretty good chance it will be a single-page app. Again, I’ve never worked on a project that large, so I could be way off.

        However, there will probably be a few cases like the one the one you outlined, in which case, I think something like your option #3 will work well. However, if the extra five modules aren’t that large overall, I might just put all the modules into one file. I think there are really a lot of variables that make it hard to say definitively.

  • http://www.123webdesignbournemouth.co.uk Web Design Bournemouth

    Yep, I’ve got about as far as putting the links to scripts at the bottom of the page for most stuff, but that’s about it.

    Many Thanks,
    Darren.

  • alexandre

    hello Andrew, got curious what is the theme you are using for this screencast

    cheers
    alexandre

  • http://www.alignmyviews.com Dheeraj

    Can anyone tell me which is the best JavaScript editor that supports intellisense as well?

  • http://www.kingkroell.co.za Thomas | Website Design & SEO, Durban

    Interesting topic. So far I’ve only been placing all javascript at the bottom of the page but does make sense to join all these javascript files into one. Will have to watch the tutorial and see if really helps clean things up and speed up my page load times.

  • http://www.imstillreallybored.com Josh

    For larger applications requireJS is a very good idea and a lot of big companies with larger scale applications use it along with AMD principals.

  • http://www.famesbond.com/ aditya menon

    I love your teachings Andrew, and when I had access to Tuts+ I totally enjoyed learning stuff from your prolific tutorials, courses and screencasts. If only Tuts+ would accept my money, I would love to get back and learn more from you and Jeffrey.