I am Hack Sparrow
Captain of the Internets.

Loading JavaScript Modules in the Browser with Component.js

The winning alternative to RequireJS and Browserify

Is there a way to enable the module loading capability of Node.js in the browser? How wonderful it would be if you could write JavaScript modules the Node.js way and load them in the browser.

There have been many attempts at doing this. Notable among them are RequireJS and Browserify. Both got things done one or the other way, but are unnecessarily complicated and a pain to use.

If you type "browserify" or "requirejs" on Google Search, you can easily see people are actively looking for their alternatives. Why are they looking for alternatives? You guess is correct - because RequireJS and Browserify are not up to the mark.

Enter Component.js, by T.J. Holowaychuk (blog post introducing Component).

Component.js solves the module loading problem in the browser in an intuitive, straightforward manner. By the end of this tutorial, you will come to the conclusion that, when it comes to loading modules in the browser, Component.js is the winner!

Component.js does much more than loading JavaScript modules in the browser[1], but in this post, I will focus on its module loading capability on the clientside, and show you how it is done using an example.

First off, install Component.js:

$ npm install -g component

Now, remember Component.js is not tied to Node.js or Express.js. It is just a Node.js module that enables module loading in the browser - on any HTML file. It generates a file named build.js in a directory called build (the directory and the file name can be customized), which endows your JavaScript with the module loading magic.

To begin the exercise, let's create a directory named component-tutorial:

$ mkdir component-tutorial
$ cd component-tutorial

Create an HTML file called app.html with this content:

<html>
<head>
    <script src="build/build.js">
    <script>
        
        var randomer = require('my-randomer');
        var random = randomer();
        document.write(random);

    </script>
</html>

Look at that var randomer = require('my-randomer'). Yes, it will work as expected. Isn't that wonderful?

Time to create our my-randomer module. It will be a very simple module, which just returns a random number. To keep our workspace neat, let's create the component in a directory named my-components.

$ component create my-components/my-randomer -l
name: my-randomer
description: random number generator
does this component have js? y
does this component have css?
does this component have html?

create : my-components/my-randomer
create : my-components/my-randomer/index.js
create : my-components/my-randomer/Makefile
create : my-components/my-randomer/.gitignore
create : my-components/my-randomer/component.json

Notice how we specified the -l options to make it a local module. Not doing so would have resulted us in having to create a GitHub style repository for our module.

Since our component is just a JavaScript module and does not include any HTML or CSS, we press y only for "does this component have js?".

The contents of the component directory:

index.js - is the module file, we implement the functionality of the module here.
Makefile - enables us to alternatively build the component using the make utility.
.gitignore - is a list directories that should be ignored by Git.
component.json - is the component's manifest file.

Here is the code for our module. Let's keep it simple:

module.exports = function() {
    return Math.random();
};

Our module is in place now. Time to build the build.js file, and make it available to app.html.

The component build command is used to build the components file (build.js, in our case).

Component.js will try to build in any directory with a component.json file. That's another way of saying, "you need a component.json file to build the components file".

Create a component.json file in the component-tutorial directory.

$ vi component.json

File: component.json

{
    "name": "app",
    "version": "1.0.0",
    "paths": ["my-components"],
    "local": ["my-randomer"]
}

You can read about all the details of component.json here. In the meantime:

paths - is a list of directories where your local components can be found.
local - is a list of local components that should be included in build.js.

With a component.json file in the component-tutorial directory, we are all set to run the build command. Let's go!

$ component build

The command will return with no output in the console, but it will create the build directory and the build.js file in it.

Now open the app.html in the browser. You can see the module in action!

There are lots of open source modules which are Component.js components, you can find them all here. A component.json file is all that's required to make any Node.js / CommonJS module a valid Component.js component.

Our example was for a local component created in the local file system. Next, let's see how we can use a component from GitHub. Let's include a component called capitalize in our existing app. Install the component:

$ component install yields/capitalize

install : yields/capitalize@master
fetch : yields/capitalize:index.js
complete : yields/capitalize

Open component.json, and you will find that the component installation process has modified component.json to add the additional component dependency.

{
"name": "app",
"version": "1.0.0",
"paths": [
"my-components"
],
"local": [
"my-randomer"
],
"dependencies": {
"yields/capitalize": "*"
}
}

Rebuild the components in the directory to update the build.js file[2].

$ component build

Now that we have updated the build file, let's update app.html file to include yields-capitalize in it:

<html>
<head>
    <script src="build/build.js">
    <script>
        
        var randomer = require('my-randomer');
        var random = randomer();
        document.write(random);
        
        var capitalize = require('yields-capitalize');
        var word = capitalize('captain');
        alert(word);

    </script>
</html>

Open app.html in the browser to see yields-capitalize also in an alerting action.

You can specify the build output directory and file name using the -o and -n options respectively. Here is an example:

$ component build -o public/components -n built.js

There is much more to Component.js than loading JavaScript modules in the browser. I will try to cover them all in the coming days. Component.js is pretty new and not many people know about it yet, help spread the word about it and tell your friends about its ability to load JavaScript modules in the browser. If anyone is looking for Browserify or RequireJS alternatives, refer them to Component.js, and this tutorial.


1. Component.js can be be used to define and load dependencies for serverside modules too, potentially replacing NPM itself. Also, it can be used to create and load modular HTML-based components for the clientside.

2. Every time the contents of component.json or any of the local modules are changed, you will need to rebuild the components file (build.js in our case).

8 Responses to “Loading JavaScript Modules in the Browser with Component.js”

  1. Benjamin says:

    Amazing, I’ve been looking for require.js alternatives for a long time and I love the way node’s nodules work.

    Had no idea about this, will definitely use in my next clientside project :)

    Great post, thanks

  2. Captain says:

    Hi Ben, amazing indeed. Thanks, and Happy New Year!

  3. srigi says:

    I will take a look at this, looks promising. Also, it is from TJ ;)

  4. Captain says:

    @srigi, definitely do. Highly recommended!

  5. daslicht says:

    hm, i dont get it running.
    I get the component built but when I open the app.html nothing is shown ?

    How to debug whats going wrong?

    I have exactly the same code as you above, and this structure was created:
    http://i.imgur.com/td90XMC.png

  6. Captain says:

    @ daslicht, make sure build.js is included in the html file, and the content of component.json is correct.

  7. JP Richardson says:

    @dashlicht, the problem is because this line in the tutorial is incorrect:

    should be:

  8. 1024bit says:

    Demand-Loading is the essential difference between Require.js and Component.js. In browser, may be the Demand-Loading is what u want.

Make a Comment