With browsers becoming powerful, developers today do a lot of computation and data management within JavaScript. With websites turning into complex web apps, the complexity of your code is also growing by the day.
Which means you’re faced with certain problems:
- Ever increasing code base gets difficult to manage
- Integrating newer libraries may conflict with your existing ones, giving you nightmares
- Unused scripts being loaded on your pages (because you are too scared to remove those old ones, thinking that they might end up breaking your app), leading to increased load times and decreased user experience.
- You have tried loading JavaScripts on the fly but that is just causing more problems, unable to resolve internal dependencies.
You may try and use one of the JavaScript frameworks that aid MVC, hence enabling you to better manage your code.
Existing frameworks like backbone.js, angular.js, etc. allow you to organise your code better with models, views and controllers. Managing navigation with routes is also made easy. That should solve your first problem, but you still have more problems to solve.
For example, consider backbone.js, where you have separate files for models and collections. In the collection classes, you have the model class mentioned. Now, requiring the collection class needs the model class to be pre-loaded. So if your collection class is loaded before your model class, backbone.js throws an error. That’s because when it parsed your collection file, your model was not available. This seems like a very small problem, but consider a large application with multiple backbone models, jQuery plugins and other data management libraries – you’ll soon find it a headache to remember and manage these dependencies.
That brings us to RequireJS – a JavaScript solution with (as described on requirejs.org):
- Some sort of #include/import/require
- The ability to load nested dependencies
- Ease of use for developer but then backed by an optimization tool that helps deployment
What is requirejs?
It is built on Asynchronous Module Definition (AMD). AMD basically loads javascript files asynchronously as required by code. This framework allows you to split your code into small modules, making it more manageable and easy to understand. It resolves dependencies between your javascript files, allowing you to specify dependency for each file separately. So if you require one file, requirejs will load all its dependency javascript files first and then will load the required file. Easy, right?
Requirejs basics
To use require.js you need to first define configure options
require.config({ baseUrl: // url to your base folder where your javascript code is, paths: { //here you can specify individual path for javascript files eg. "jquery": //path to your jquery file }, shim:{ // here you can specify dependencies for your files eg. "backbone": [“underscore”] } });
As stated above, using shim, you can specify dependencies in requirejs. It will take care of loading your dependencies before loading any file so that you don’t need to worry about file order.
Let’s consider an example of how you can define a module:
define(“hello_module”,[“jquery”,”underscore”], function($,_) return { alert_hello: function(){ $(“button”).click(function(){ alert(“hello”); }); } } });
In above example “hello_module” is the name of your module, “jquery”,”underscore” are the module dependencies and inside the function you can write your code.
You can use this defined module in another javascript as follows:
require([“hello_module”],function(hello_module){
hello_module.alert_hello();
});
The basic difference between define and require is that code in require is executed as soon as a file is included, whereas define only defines a module – same as we define a function – which can be used anywhere.
Requirejs Optimizer
Requirejs has its own optimizer called r.js. It optimizes your requirejs module by combining all your dependencies that are stated and putting it in one file. This output file is also minified using uglifyjs.
For example:
define(“testModule”,[“a”,”b”],function(a,b){ });
If we optimise this file using r.js we will get the final output as follows:
define(“a”,[],function(){ }); define("b",[],function(){ }); define(“testModule”,[“a”,”b”],function(a,b){ });
So dependencies “a”,”b” are combined with the original file to produce a single output. All that is required to define testModule is now present in a single file, thereby allowing you to minimise size and manage js payload. Hence, there will not be a separate request for dependencies as the dependencies are present in the same file. The problem with this is that if there are N number of dependencies on a module, this module will be included in N number of files. However, this can also be taken care of. There is an option in r.js to ignore files that are frequently required by modules.
For example, jquery is frequently used in most of our javascript code. So if we go on optimizing files, each file will prepend code for jquery.js, which is not good. Instead, you can specify“paths.jquery=empty:” while running the command so r.js will ignore the jquery dependency and it will not get prepended in the output file.
To sum it up, RequireJS is a better way to organize, manage and maintain your javascript code and their dependencies. But this was just an introduction – stay tuned for more, a post on how to build a basic application using requirejs is coming soon!
Leave a comment
Comments (0)
Be the first one to comment.