Use aliasify to include configurations in your web application

As I build more web applications, one problem that I keep running into is how to include application configurations into the application source code.

What do I mean by configurations?

They include application-specific settings such as the application name, API URL, debug mode etc. These are metadata to the application, similar to the metadata contained in package.json for a Node module.

As I develop most of my applications locally, some of these settings will differ when the application is served on localhost versus when served in production. For eg., I usualy use a staging API server for local development and then a production server for deployment.

I could certainly hardcode these settings into the source code right?

The fact that I need 2 (or more) environment-specific versions of these settings make them difficult to be hardcoded. Furthermore, as a developer, I feel a little “dirty” when I hardcode these settings. Ideally, they should be declared in a JSON file somewhere, just like package.json.

There must be other solutions out there!

Surprisingly, there isn’t a good straight forward solution out there, as far as I know (if you know of one, please leave a comment). Here are a few worth mentioning:

One can follow the approach outlined by Addy Osmani in making environment-specific builds with build tools and use some sort of string replacement plugin. However, this will introduce some ‘not-so-pretty’ delimiters in the codebase, such as @@foo used by grunt-replace.

Henrik Joreteg’s clientconfig is another elegant solution and very close to what I have in mind, however it relies on a server component to set all the configurations in a cookie. This is not a hard requirement, but is not feasible for a static site running on a simple file server (such as Github Pages) like this blog.

Another attempt at solving this problem

If you are using browserify to bundle your JavaScript code, this might be a good solution for you.

Using aliasify, you can require your config, which is declared in a config.json file like this:

{
    "API_URL": "http://example_server.com/api",
    "env": "development"
}
var config = require('config');

console.log(config.API_URL); //prines out API_URL
if (config.env === 'development') {
    // do something specifically in development mode
}

To declare this transformation, you can add the following section to package.json:

{
     "aliasify": {
        aliases: {
            "config": "./config.json"
        }
    }
}

Pretty simple, right?

Environment-specific configs

We can make this even better, by allowing for environment-sepcific configs. To do that, I recommend using a build tool like grunt or gulp. I am sure there is probably a way to do it with just the simple browserify command line interface, but using browserify programmatically makes things a lot easier.

Here’s an example of how I am using this in a recent project:

// gulpfile.js

// enable development mode
var dev = false;
gulp.task('enable-dev-mode', function () {
    dev = true;
});

gulp.task('scripts', function () {
    // set up browserify bundle in here
    // see https://github.com/gulpjs/gulp/blob/master/docs/recipes/browserify-uglify-sourcemap.md

    // aliasify config
    var aliasify = require('aliasify').configure({
        aliases: {
            'config': './config' + (dev ? '.dev' : '') + '.json'
        },
        configDir: __dirname
    })
    bundler.transform(aliasify);
});

In this approach, aliasify will automatically use config.dev.json for development environment and config.json for production one.

A similar approach could be taken when using grunt-browserify. In fact, it is probably easier to do environment-specific stuff with grunt due to its ability to declare a task target.

There you have it, a simple approach to accessing environment configuations in your project that is made possible by browserify.

What’s bad, what’s good, what could be better?

This solution’s downside is relying on browserify (and possibly a build system), which might not be applicable for an older project. If you use RequireJS/AMD, I imagine it’d be similarly easy to include such a config file using the JSON plugin.

One possible improvement to this solution is allowing the ability to cascade configs across environment. For example:

In config.json

{
    "appName": "FooBar",
    "apiUrl": "http://foobar.com/api"
}

And then config.dev.json just “extend” it without redeclaring common configs:

{
    "apiUrl": "http://localhost:3000"
}

This is currently not possible with using aliasify. I have implemented a similar version of this as a grunt task for tobiko, but it’s not polished enough to be used by others yet. I will update this space if and when this becomes available.

Handlebars templates with Backbone, grunt.js and RequireJS

Integrating Handlebars templates in modern web development workflow has been crucial in helping me organize my code neatly and maintain sanity. I want to achieve a few things:

In a current Backbone.js application at work, which is set up with grunt and RequireJS (you can find a similar set up with the default yeoman backbone generator), I have found the following set up to meet most of these goals.

I can use the templates with RequireJS in the views like so:

// viewOne.js

// I use commonjs syntax with require
// http://requirejs.org/docs/whyamd.html#sugar
var Templates = require('templates');
var viewTemplate = Templates.viewOne;
var html = viewTemplate({data: 'test'});

The template directories look something like this

app/templates/
├── viewOne.hbs
├── viewTwo.hbs
├── viewThree.hbs
├── ...
└── viewTwentyThree.hbs

0 directories, 23 files

I use grunt-contrib-handlebars to compile the templates. Here’s the Gruntfile.js config for local development:

handlebars: {
    compile: {
        options: {
            amd: true,
            namespace: 'Templates',
            partialsUseNamespace: true,
            processName: function(filePath) {
                var file = filePath.replace(/.*\/(\w+)\.hbs/, '$1');
                return file;
            }
        },
        files:{
            '.tmp/scripts/templates.js': ['<%= yeoman.app %>/templates/*.hbs']
        }
    }
}

The above code does a few things. More detailed explanation of what each options does can be found on the plugin github page.

In the build step for deployment, instead of just outputing the compiled templates into the .tmp folder, RequireJS can put Templates in the optimized javascript with the following Grunt task config (note the paths option):

requirejs: {
    dist: {
        options: {
            baseUrl: '<%= yeoman.app %>/scripts',
            optimize: 'none',
            paths: {
                'templates': '../../.tmp/scripts/templates'
            }
        }
    }
}

This simple set up has allowed me to rapidly develop a complex apps by breaking down complex templates into small reusuable components and use them liberally anywhere with RequireJS, yet keep the built JavaScript minimal and compressed. I hope it will be useful for others who might be looking for a similar solution. If you find this useful or would like to suggest an improvement, please leave a comment.

cbtallc.com redesign launched!

I started working with Jim and CBTA LLC. on their website since 2010. In fact, it was the first ever WordPress site I built, marking the beginning of my web development career. It was the good old days of buying a standard theme (for $40 or so if I remember correctly) and then customizing it through ONE single custom stylesheet, inline styles and inline scripts. With all of that, I was able to create a homepage with carousel and a Google calendar page for appointment scheduling (see the screenshots attached). I was pretty proud of myself for this.

Old Site Homepage

Old Site Appointment Page

Fast forward 3 years, the old way of using a paid theme of using inline styles and scripts became unsustainable as the practice’s needs expanded. And while I have learned and grown so much more as a WordPress developer, having built many custom themes and functionalities, I felt that WordPress was an overkill for a site like cbtallc.com. The concept of a server-side architecture with database queries became clunky for a site that requires so many custom pages and functionalities yet few content iterations. I was responsible for updating few content changes, yet unable to implement new cool features. This is when I decided that a static-site generator would suit the needs of this page better.

Having just released tobiko and used it on this personal blog, I decided to use it to power cbtallc.com version 2 as well. Thus began a very exciting process for me of stripping a rather standard business-y site originally into a more modern and minimal looking site, preserving the original functionalities yet making it more open to new features. I wanted to reduce the number of pages a user has to click through to consume the information that matters to them. All of this while keeping the site as clutter-free as possible, keeping in mind the potential audience the site would attract. Last but not least, while the amount of mobile and tablet usage was low, I believe it was because the old site could not be as mobile-friendly as it should be. So the new site was developed with responsive design baked in from the start.

New Site Homepage

New Site Appointment Page

Having said all that, I am not a designer by training, so I’m sure there are probably more design violations committed in the new site than legally allowed. But I think I am more okay with that, because the whole static-site architecture that tobiko provides allows the developer me to iterate quicker and make more frequent small improvements over time. This is actually what I am happiest about the new site - the new build process that is baked into it. I won’t go into depth on the benefits of tobiko here, and there are plenty, but that’s for another post.

The practice’s appointment schedule system is improved with newer tools, including fullcalendar and Twitter Bootstrap modal. A user can now select an appointment request right from the calendar without typing in the date and time repeatedly as before. The new site also exposes information about therapists at the practice and treatments offered in a way that requires less friction from the users (fewer clicking and page refreshes), which hopefully will amount to a smoother overall experience. So there are also clear UX and content wins with the redesign as well, in addition to the behind-the-scene stuff.

There are certainly many areas the site can be better, including a cleaner, friendlier calendar display and deeper content engagement with the audience through blog posts (which is thankfully built in to tobiko). These challenges and improvements will definitely be worked on as I embrace a more agile approach in developing the site. As for these past couple weeks since the soft launch, I am pretty happy that a website that started it all for me gets a facelift and hopefully serves its users better. Check it out at http://www.cbtallc.com.

Meteor and Bower

I have been using Meteor.js for one of my projects in the past few months. After working with WordPress and the LAMP stack for a while, I quite welcome the new and refreshing environment Meteor has to offer.

When I first started with Meteor, the one thing I sorely missed from building other web apps was the ability to use bower to manage front-end dependencies. I have come to rely on bower to get me the latest copies of libraries and put them in a consistent place. Meteor, however, has its own way of managing packages and isn’t fully compatible with bower right off the bat.

After some digging around on StackOverflow and jumping on the IRC channel, I figured that there was no perfect way to integrate this. So I decided to create a little hack to make bower works with Meteor. The package that sparked my desire to make this work was bootstrap. I posted an earlier version of this post on StackOverflow.

Where to put bower_components?

This was the first question I had to answer. Since Meteor automatically packages any .css and .js files in the client folder and serves them, client is not a good idea to put these dependencies, as they most likely have a bloated number of files you don’t actually need.

I found public to be a good place to keep these files, since “Meteor server will serve any files under the public directory”.

{
  "directory": "public/bower_components"
}

How to use these assets?

Any static files (.css, .jpg, .png, .svg and so on) can be sourced like this:

<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/>

less files can also be included in your authored less code as well:

@import "public/bower_components/bootstrap/less/bootstrap.less";

Notice the path above include the public folder.

Explicitly declare files to be included on the client

While the above method for static files works fine locally and on sites deployed to meteor.com, it fails when the app is deployed to heroku. Furthermore, it would not work for JavaScript files since Meteor templates do not execute any <script> tags in the body the way one would expect.

In order to overcome these challenges, I use a small hack.

 ❯ tree packages
packages
└── bower-dependencies
    └── package.js
Package.describe({
    summary: "Load bower dependencies."
});

Package.on_use(function(api) {
    // bootstrap
    api.add_files(['../../public/bower_components/bootstrap/dist/js/bootstrap.min.js'], 'client');
    api.add_files([
        '../../public/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot',
        '../../public/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg',
        '../../public/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf',
        '../../public/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff'
    ], 'client');
    // ladda-bootstrap
    api.add_files([
        '../../public/bower_components/ladda-bootstrap/dist/ladda-themeless.min.css',
        '../../public/bower_components/ladda-bootstrap/dist/spin.min.js',
        '../../public/bower_components/ladda-bootstrap/dist/ladda.min.js'
    ], 'client');
});

This will make the static assets available at the proper URL. For example, to use the glyphicon fonts in this case, the URL would be /bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot.

This package will also serve any JavaScript and CSS files automatically, as they are gathered and bundled by Meteor before serving.

Install bower dependencies when deployed to Heroku

Since using bower is not a very popular pattern among Meteor developers, bower dependencies are usually left out on deployment because the bower_components folder is usually gitignor-ed and thus not included in the source code.

When deploying my app to heroku, I use this heroku-buildpack-meteorite. In order to make bower works, I added the following lines of code after packages are installed and before the meteor bundle is built:

echo "Installing bower" | indent
run_npm "install bower -g"
echo "Bower installed" | indent
echo "Installing bower dependencies" | indent
HOME="$BUILD_DIR" bower install |indent

This code is submitted as a pull request, but I also maintain a fork that has this added support for bower.

Conclusions

I hope my solution will be useful for people who would like to stay with bower for front-end package management in the Meteor world. I am aware that Meteor and Meteorite projects have official support for many important packages, including bootstrap used in this example. However, depending on those packages add a layer of delay into your workflow, as updates will not be as quick as the original. This was true for me back in September when I wanted to use Bootstrap 3 as it was released to the public. Meteor did not have support for it until much later. It is for good reason - they want to make sure things are stable and safe before pushing out an update, and probaly want to time it with their release cycle as well. However, as developers, sometimes we get itchy and want to take new things still under development out for an early ride. That is what bower is there for, so why not use it, right?