Creating a yui module for use in node

Overview

A brief look at how to structure and develop a YUI based module for use within node.js & express.js.

This tutorial assumes you are already familiar with the basics of setting up an express.js based application, if not, you should at least read the express guide.

For the purpose of this example, our module will be called the bakery. The bakery itself will provide a single model: cookie.

One assumption going into this process is that we want to expose our yui module so that it can be used in two different ways. First people should be able to directly require the module and use it without having to think about the fact that it uses YUI or do any additional setup. Second, if an app is already configured to use YUI, we want to be able to load our module into their current YUI instance and use it.

As always, this tutorial was put together for me to learn more about the process of setting up yui and express so it is possible that there are mistakes or inferences that will need to be corrected.

Getting started

When developing a module I like to create a new express app and develop the module local to that app. By creating a new app for each new module developed, I ensure that existing settings don’t impact the module. It also ensures to that the module conforms to the latest node.js/npm standards.

To get started navigate to your typical working directory and type express bakery_testapp. By default, this will setup a standard express app that uses jade as it’s templating language.

Now, we want to install express and jade local to our app. This ensures that our app is locked down on a version of express and jade until we choose to upgrade it. First, cd into your test app: cd bakery_testapp. Then run: npm install.

This will create a new subdirectory inside of bakery_testapp called node_modules. This will contain the two node packages (express and jade) that our express app relies on. This also is where we will create and work on our new module.

Our next step is to create the basic scaffolding of our module. This includes the directory structure, required build file and configuration files, and empty source code. To do this cd node_modules and create the following directories and files:

    • bakery
      • package.json
      • index.js
      • src
        • bakery
          • build.json
          • js
            • bakery.js
            • cookie.js

At this stage, we have a structure built but we have a bit of work to do before we have a working module.

What are these pieces and how do they fit together?
First steps
The first thing that we have to do is to adjust package.json so that it is a valid configuration file. Thankfully npm can do a lot of the heavy lifting for you. First make sure that you are in the same directory as your package.json file and then type: npm init and answer the questions. Once you done, you will now have a valid package.json file.

What are those fields? The answers are best found: package.json.nodejitsu.com

This also means that our module is now a valid node module and should be usable without any errors (it also won’t do anything yet) but we should still test this.

So, go back to the top level of your apps directory structure and edit the app.js file to include this line:

Right before the line

If we run node app in our terminal our express app should run and should properly require our module.

But how do I know it worked, it didn’t say anything? Well. Let’s add a little proof. cd into node_modules/bakery and add this line to index.js

console.log(“Bakery required”);

Now cd back to the top level of your test app and type: node app and it should print to the shell “Bakery required” and then start the express server.

Setting up the YUI module

The next step is setup the YUI module so that it builds and has some very basic functionality. Let’s start by having it build a YUI module that defines the bakery namespace. We should always develop modules that namespace their functions and classes. It makes our code “play better with others” To look at the details of this, read: A JavaScript Module Pattern. The actual methods for defining namespaces in YUI has changed slightly but the logic behind it hasn’t.

To setup our build file we will edit to look like this:

This basically says that our bakery module only builds one thing. The bakery and that it only needs to process one javascript file: bakery.js This module is not dependent on any other YUI modules.

So let’s add the code to bakery.js that will create the bakery namespace. Simply open up src/bakery/js/bakery.js and add the lines:

Y is the YUI instance that will be passed to our module when it is loaded. YUI’s namespace function will create a namespace if it doesn’t already exist. Otherwise the existing namespace will be left as currently defined.

We can now build a fully functional YUI module by changing or working directory to src/bakery and typing shifter in the command line. After a few hundredths of a second we will have new subdirectory under our node_modules/bakery directory: build is the output of shifter, a valid yui module that could be included directly in a web page, loaded as a yui module and instanced, but we have a little more work to expose this module to node.js.

Exposing our YUI module to node.js

The first step in exposing our YUI module to node.js is exposing our dependency on YUI. So, open up package.json and add this entry:
“dependencies”: {
“yui”: “*”
},

This instructs node.js that our package is dependent on YUI.

You also need to update the package.json file for our express app to include the same dependency. Currently it depends on jade and express. Add yui to the dependencies list and run npm install yui so that we also have the local copy of yui installed.

Next we want adjust index.js to do all the work of loading the module.

So, what is happening here?

First the meta variable. YUI provides the ability to dynamically load modules. In order to do this you must provide YUI with a configuration dictionary for each module that will loaded. This is described in detail in the documentation on dynamic loading.. In this case our module configuration only needs to describe one YUI module: bakery. That YUI module only relies on only one other YUI module: model. We also include the full path on disk to the javascript file that will need to be loaded.

The meta variable will be exposed to node.js through module.exports and will be used when you want to load the bakery within an existing YUI instance.

Next, we export the function create_yui_instance() from our module. This allows the user of our module to access it’s functionality like so:

This provides a nice simple abstraction for people using our module that do not want to deal directly with YUI. They simply load our module, “instance a bakery” and then can call our documented routines from that instance. There is an additional, and beneficial, side effect to this approach; since we return a YUI instance we can use that YUI instance for any standard YUI operation. For example, the bakery model already loads the Model module so we can do:

For those users who want to add our module into an existing YUI instance, then use this form of interacting with our module:

If you are planning on using your yui modules within node.js using express, then express-yui provides a convienent way of integrating YUI with express.

Additional reading

Using shifter to build a YUI module
Node.js yui package
package.json.nodejitsu.com

LevelsOfThinking