I first looked at Node.js because it sounded like they had bridged the gap between client side (browser) and server side (Node.js). Code re-use is one of the core principles of developing software and for some reason it has taken us this long to get to a point where we can write one language that can be reused on both server and client side.

My initial impressions of Node.js bridging this gap weren’t great. Node.js does a good job of running stuff server side in JavaScript, but finding documentation on how to share code has been a slow process. The documentation on their website doesn’t mention sharing of code between client and server.

Current state of affairs

Node’s server side code exposes public methods/properties with a module pattern

If you want to expose a public method called doCoolStuff in your Awesome.js file you might do this:

exports.doCoolStuff = function() {

// Cool stuff done here...

};

However when we go to run Awesome.js on the client – it’s not going to know anything about what an exports is.

Solution

There are various ways around this such as checking whether exports exists, if it doesn’t define it etc… (read more here)

My preferred solution is to use Require.js and kill many birds with one stone. From the web browser point of view, Require.js is really helpful in that it:

  • Allows us to asynchronously load JavaScript resources
  • Allows you to get rid of script includes from your HTML
  • Negates the issue of having to order JavaScript files one after the other
  • Greatly improves on the ability to test our code by swapping out concrete implementations with mocks/dummys
  • Cleans up your code a lot
  • Better way of specifying modules

Also we can use the same code on the client and server (Node.js).

Setting up the Server Side (Node.js)

I tried to install via NPM a la – npm install requirejs, however NPM couldn’t download and unpack the files for some reason.

To get around this I downloaded the r.js code for node directly from the Require website, renamed to index.js and placed it in a folder called Requirejs in the node_modules folder. I renamed it to index.js as node will automatically look for a file called index.js in folders in node_modules.

Server Side Code – Server.js

var requirejs = require('requirejs');

// Boiler plate stuff - as per r.js's instructions
requirejs.config({
    //Pass the top-level main.js/index.js require
    //function to requirejs so that node modules
    //are loaded relative to the top-level JS file.
    nodeRequire: require
});

// We are requiring Person, instantiating a new Person and then
// reading the name back

// As Person.js is a module, we dont need the .js at the end
requirejs(["/Path/To/Person"], function(Person) {
	var person1 = new Person("Seb");
	console.log(person1.getFirstName());
});

Code that can live on client or server – Person.js

define(function() {
	return function(firstName) {
		var _firstName = firstName;
		
		this.getFirstName = function() {
			return _firstName;
		};
	}
});

HTML Page

<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        <!-- data-main attribute tells require.js to load
             scripts/main.js after require.js loads. -->
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>

JavaScript for the HTML Page – Main.js

// We are requiring Person, instantiating a new Person and then
// reading the name back

// As Person.js is a module, we dont need the .js at the end
require(["/Path/To/Person"], function(Person) {
	var person1 = new Person("Seb");
	console.log(person1.getFirstName());
});

More Reading

There are some rules around relative paths for your requires. It’s well worth spending the time and reading over them at the Require.js website.

Require.js talking about what Asynchronous Module Definition is

About these ads