Check out the series introduction post for a list of all the birds and their attack powers.
Yellow Bird Attacks
In this post we will take a look at the Yellow Bird who comes with a RequireJS speed booster and dynamically injects scripts against those pesky swine. Slowly, one by one, the birds will take back what it theirs to keep!
What Was Stolen by the Pigs?
The birds used to manually add script tags to their HTML files. At first this wasn't an issue, but when their application started to grow larger and more complex it started to become difficult for them to organize their code, figure out dependencies, and determine a strategy for optimizing performance. Thankfully they were introduced to the RequireJS library which provided them a way to manage their code into modules, load their scripts asynchronously, manage their dependencies, and provide an easy way to optimize. Unfortunately the pigs, during a recent invasion, stole the RequireJS library from the birds.
One of the yellow birds has been tasked to reclaim what has been stolen. He will use the optimization power of speed to help destroy the pigs in order to take back what is theirs.
Let's first start with a simple little web page that contains just a few scripts. You'll notice that I'm loading 3 popular libraries (jQuery, Underscore, and Postal) and some custom code at the end.
The above code looks pretty straightforward, but when I end up running the page I get the following error in the dev tool's console...
Fictitious Internal Dialog: "WHAT!?! I don't see any
eachmethod anywhere. What's up with that? Ohh man, it looks like the exception occurred in postal.min.js somewhere. FOUND A BUG... see if I use that library again. But, wait!?! Ohh, maybe something else is going on here."
So, the real issue isn't a bug in postal.js, the issue is in that postal.js has a dependency on underscore.js. The problem is that underscore should have been loaded before postal.js. Simply rearranging the script tags could easily solve this issue. In the above case the fix was trivial, but imagine how cumbersome this could be once the project starts to get large and requires lots of scripts.
Before we go and look at how we could fix the above situation using RequireJS, let's first take a high level overview of what the library is doing for us. RequireJS is an Asynchronous Module Loader and the API it provides allows us to define and require modules. Both functions are really easy to understand so let's take a look at them.
In order to create a module you need a name, a list of dependencies, and a callback function.
At some point in your application you will need to use the
requirefunction to kick things off.
Using RequireJS I took the above little application and rearranged some things. You should notice that the following markup removes all the script tags except one, which points to the require.js library. RequireJS knows where to start because we add an HTML5 data-main attribute describing where the main script is located.
The main script has a configuration section inside of it where you can assign aliases to existing AMD modules and also shim libraries that were not previously defined. Although jQuery and Postal define themselves as AMD modules we included them in our configuration because they are not located alongside
You don't have to include in your config any custom modules you define in your application. You can refer to those by their file path and name.
Our application only has 5 script files in it, but as you know our app will only continue to add additional scripts. So, it would be nice if there was an easy way to combine and minify our scripts for better production performance. The nice thing is that by using RequireJS we have already defined the dependencies of our application.
Thankfully there is a tool called
r.jsthat takes this dependency information and uses it to generate a combined and minified script. You can install the tool with the Node Package Manager
npm install requirejs
You could provide all the command line argument to the tool in the console, but I prefer making a build config file like the following to define all of its settings before I run it. You can find a comprehensive list of settings from the official GitHub repository.
Once you've defined your
build.jsfile then you let
r.jsknow you want to use it. The following command will get you going...
r.js -o build.js. You can see the output of the tool in the output below.
I only scratched the surface on all the things you can do with RequireJS and the r.js optimization tool. If you are interesting in learning more about these concepts you may want to look at some of the following resources.
- Jack Franklin's (@jack_franklin) Introduction to RequireJS article
- Jeffrey Way's (@jeffrey_way) A RequireJS, Backbone, and Bower Starter Template screencast
- Cary Landholt's (@carylandholt) RequireJS Basics video
- Jonathan Creamer's (@jcreamer898) Using Require.js in an ASP.NET MVC application article
space barto launch the Yellow Bird and you can also use the arrow keys.
Front-end web applications can get complicated quickly. It is nice to have a way to provide some structure, dependency management, and an easy way to optimize the final result. Thanks to the power of Yellow the birds have regained their trusty RequireJS tool for use in their next application.
There are many other front-end architecture techniques that have been stolen by the pigs. Tune in next time as the next Angry Bird takes its revenge! Dun, dun, daaaaaaa!