(Re)Learning Backbone Part 5

(The current code base can be checked out here)

Front End Build

Often at this point in a project, I will get derailed. I'll start thinking about dependency management, should I use Grunt or Gulp or Broccoli or ... to build the project, module definitions, and the like. The combination of all these options just multiplies and I'll spin until I lose interest in the project for awhile.

Tasks like minification and image optimization and static analysis are important parts of a production application but we still haven't written one line of front end code. In the spirit of XP, I did the simplest thing possible that still works.

My requirements: I wanted to declare my Javascript dependencies on the fly. I always forget to add them individually to my index.html file. I want to declare them explicitly so that different sections of the code could be loaded independently when it comes time to optimize the app. This also has the side benefit of allowing my IDE to perform better autocompletion. I wanted all of my assets to be accessible from the simple web server we created earlier without a separate deploy step. Once we have a working app, we can then go back and figure out how to serve up the bare minimum.

To accomplish all of these tasks, we are going to use two tools: Bower and RequireJS. Bower will handle the management of third-party libraries and RequireJS will handle our dependency management and loading of files. There are other options, especially for RequireJS, such as Browserify. Feel free to explore them and pick one you are comfortable. The way you modularize your code will be a part of every file you write, so be happy with your choice.

Bower

Bower, like Node's NPM, allows you to automatically retrieve libraries from the net, and manage them and their dependencies. To install it, run

npm install -g bower  

One quick customization we are going to make is where Bower stores its dependencies. Typically, we would keep them at the same level as our node_modules dependencies, and use a build tool to copy the specific JS and CSS files we need into our app. To avoid this, we will store our dependencies under our public directory so that our Node server can serve them up directly. This has the side effect that ALL files that come with the packages are accessible, such as READMEs and package files, but until we have a working app, this is a reasonable trade off. In your project directory, create a file called .bowerrc with the following contents:

{
    "directory":"public/components"
}

With this complete, run bower init, answer the questions and finally end up with a bower.json file that looks similar to:

{
  "name": "relearning-backbone",
  "version": "1.0.0",
  "homepage": "https://github.com/bmajewski/relearning-backbone",
  "authors": [
    "Brian M <hireme@brianmajewski.com>"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "public/components",
    "test",
    "tests"
  ]
}

We're now set up to use Bower to pull in our other dependencies, including RequireJS.

RequireJS

To effectively use RequireJS, you really should go and read through the docs once or twice first. Go ahead, I'll wait. Done? Ok - It may not make a bunch of sense if you are new to this type of module management. Hopefully, as we work with it, it will become clearer.

In a nutshell, Require (I'm going to drop the JS from here on out) will allow us to specify just one Javascript requirement in our index.html file. From there out, it will dynamically load additional files as we need them without us having to explicitly add them.

To set this up, we'll update our index.html and create a configuration file for Require. To install Require, run:

 bower install requirejs --save

If you look under public/components, you'll see the newly installed package.

There are differing opinions on where to put Javascript declarations and how they effect initial download and rendering of your home page. For simplicity, we'll place our declaration in the <head> of our document, beneath our styles.

<head lang="en">  
    <base href="/">
    <meta charset="UTF-8">
    <title>Relearning Backbone</title>
    <link rel="stylesheet" href="assets/css/styles.css">
    <script src="components/requirejs/require.js" data-main="require-main.js"></script>
</head>  

As you can see, we've added a non-standard attribute to our script tag: data-main="require-main.js". This tells Require where to read its configuration information.

Go ahead and create the file require-main.js under public, with the following contents:

requirejs.config({  
    baseUrl: "app",

    paths: {

    }
});

require(['main']);  

This is (almost) as minimal of a config file we can use and have it still be useful. At the top, we call config on requirejs and set some properties. baseUrl is where require should look for all files we haven't explicitly defined. paths are those explicitly defined files (and is empty for now). Next, we invoke require with an array of files we need to load. Typically, you would declare those files, and then a function, assigning those files to variables, and do something with them, such as:

require(['moment'], function(moment){  
    moment.format();
});

which would load the Moment library and display a formatted datestamp.

In this case, we are telling it to load the file main and process its contents. Our main file won't return anything - it will actually load up our application and start it up. Since we have't defined main in the paths block above, Require will look for app/main.js, so let's create an app directory and a main.js file with the following contents:

define(function (require) {  
    console.log('require module loading working');
});

All of our Javascript files will have this basic format: a define function that takes require as an argument. We'll be able to use this parameter later to load other files.

If you reload index.html, you should be able to see our message in your console window. This let's us know that we have Require wired in and loading our modules.

Spit And Polish

Before we get into the meat of designing our home page and screens to access the user data, I want to add a little bit of styling to the app. I find that if I leave things a little too "raw" I'll waste time trying to clean them up a bit. At this point I would usually grab Bootstrap to provide a simple clean interface. But... should I use the plain CSS, or maybe the LESS or the SCSS... Do I need to add a CSS preprocessor to my build pipeline? What about all the Javascript components, should I add them in too? Will they conflict with the stuff I want to write later? Oh hey, what about trying Susy for a grid layout? And on and on it goes. Once again - DERAILED Here is what I do now. I go to Bootswatch, pick a color theme that I like in the moment, download the CSS file, put it in assets/css, add it to my index.html file and I am done with CSS until it comes time to actually build my app and its feature set.

Next Steps

With our package management and module loader in place, we're ready to start building out our client application. Next time, we'll create a simple router, a message bus, and main layout that will allow us to swap different content views in as needed.

(To grab the code at this point in the series, checkout commit: 82df0f2fd5bdc91d5599aa1c40faacca38766327 from Github)