4 strategies for passing parameters to RequireJS modules

RequireJS is a great library for managing JavaScript files, modules and the dependencies between them. This post requires (pun intended) some knowledge of the framework. If this is all new to you, point your browser to requirejs.org to find out what all the fuzz is about.

Introduction

Recently I took upon me the task of cleaning up all the JavaScripts in a web application (built on ASP.NET) where total script anarchy had ruled for years. You could find scripts all over the place. Needless to say, RequireJS became my weapon of choice to bring order to the chaos.

As in many (probably all), server-side web applications, I found my self wanting to pass server-side data into client-side scripts. So the question was: How can I do this with RequireJS? This blog post is a summary of 4 different strategies to achieve this.

Setup

To keep it simple, I'm going to use JavaScript to display an alert box with a greeting based on the input given. In the spirit of keeping things simple, the input is only hardcoded strings.

#1 Passing parameter to method

Starting of slow, we let our require module return a JavaScript object with a method that accepts a parameter. This is pretty basic stuff, and should be sufficient for most scenarios.

index.html
<script src="scripts/require.js"></script>
<script>
	require(['scripts/app'], function(app){
    	app.greet('World');
    });
</script>
app.js
define(function(){
	return {
		greet: function(name){
			alert('Hello ' + name);
		}
	};
});

#2 Passing object to method

While #1 works great when you have one, or only a handful of parameters, it can get quite messy when you're dealing with a lot of parameters. To counter this we can let our module accept an object instead.

index.html
<script src="scripts/require.js"></script>
<script>
	require(['scripts/app'], function(app){
    	app.greet({
        	salutation: 'Dr.',
            name: 'Who'
        });
    });
</script>
app.js
define(function(){
	return {
		greet: function(config){
			alert('Hello ' + config.salutation + ' ' + config.name);
		}
	};
});

#3 Using RequireJS configuration

By loading the pre-defined RequireJS module aptly named "module" into your own module, you can define and access configuration data.

Note: The definition must be done before you include the require.js file, and this only works for define and not require modules.

index.html
<script>
	var require = {
		config: {
			'app': { //This must match your module name
				name: 'Sherlock'
			}
		}
	};
</script>
<script data-main="scripts/app" src="scripts/require.js"></script>
app.js
define(['module'], function(module){
	alert('Hello ' + module.config().name);
});

#4 Using a separate configuration module

Sometimes you'll have multiple modules needing the same input, then you can define a separate configuration module, and load it into your module like any other. I think this gives an nice clean separation between logic and data, but it can be a bit of an overkill i many situations.

index.html
<script>
	var require = {
		config: {
			'config': {
				name: 'Everybody'
			}
		}
	};
</script>
<script data-main="scripts/app" src="scripts/require.js"></script>
config.js
define(['module'], function(module){
	return {
		name: module.config().name
	}
});
app.js
require(['config'], function(config){
	alert('Hello ' + config.name);
});