Monday, January 12, 2015

Browserifying all the things

To quote a famous author,who if this blog post is to believed has started writing Javascript:
        "It is a truth universally acknowledged, that a good Javascript developer who writes           Node.js code  loves the CommonJS module format."
Before you read the rest of this article,if you are unfamiliar with browserify read the browserify handbook , if you are interested in figuring out more about alternate module systems such as requirejs .If you are unfamiliar with the module pattern go here and if you want to know why polluting the global module system is bad go here. I would rather you use these resources than have me butcher them while trying to explain them.If you are already using either the ES6 or System.js modules ,there is a ton of things you could teach me,so go on gloat over it.

Another interesting aspect is that managing your project's dependencies is easier because each dependency is listed in the package.json,this means that anyone else who works use your code , work with as either a developer,a plugin/middleware creator or as an enduser will understand the dependencies on the project and will be able to add their own in a way that is entirely transparent.

But there is more to it than just the explicit listing of dependencies,you do not need to add these dependencies to a git repository , thereby keeping it minimal , you could use npm install to install all these dependencies just as easily.

Now, imagine a scenario where you can use npm install to build all your server-side and client-side dependencies all at the same time. Ofcourse , this will also setup your grunt or gulp task runner along with any of the required tasks as well. This frees a lot of your time from chasing after dependencies that you already know you want to use or version mismatches which cause works on my system bugs when setting up a new project or setting up development environment on a virtual machine (beware of the virtualbox bug that does not allow symlinks and makes it difficult to setup cli tools) or a coworker's environment.

This is , I believe the appeal of using browserify which allows you to use the time-tested CommonJS module system , bundles your code and all of your actual dependencies(just the ones you need , not the ones you decieded to install but never use) into a single file with source map support for debugging.

And then there are transforms which allow you to dynamically compile only the handlebars template you require just before bundling , allow you to require that are built for amd only or available with bower only , compile coffeescript to javascript , compile from either SASS or LESS to CSS. Take a look at all the transforms available here . 

But , you have an understandable question , how would I load jQuery and jQuery plugins with it , certain CSS frameworks and Backbone need jQuery to be available either as jQuery or $ on the global scope.This does not solve any of my problems , it does not work for me ,it looks like an individual selling encyclopedias on the sidewalk , well dressed but offering a product that is of absolutely no use to me , you might say.

Before you slam the door in our collective faces(mine and browserify's,just because it is a module loader does not mean it does not have feelings) , listen to this , you can shim modules that are not written to take complete advantage of the commonjs module format or modules that are required by other modules to be available on the global scope using a transform called browserify-shim . 

(1) Loading Bootstrap/Semantic-UI and jQuery

jQuery has been published as an npm module that does not require shimming for a while,so you can just:

        npm install jquery --save

and 
     
       var $=require('jQuery');

Bootstrap is also available as an npm module,you can add the css to your html the same way you usually do it or you can require it using cssify or browserify-css(which supports concatenating and minifying css into a single style tag with a data-href attribute).

To shim the javascript,use this config which is an excerpt from my package.json:

 "dependencies": {  
   "bootstrap": "^3.3.1",  
   "jquery": "^2.1.3"  
  },  
  "browserify": {  
   "transform": [  
    "browserify-shim"  
   ]  
  },  
  "browser": {  
   "bootstrap": "./node_modules/bootstrap/dist/js/bootstrap.js"  
  },  
  "browserify-shim": {  
   "bootstrap": {  
    "depends": [  
     "jquery:jQuery"  
    ]  
   }  

The browser property allows you to create aliases to javascript files that you need,now go ahead and use these files within the browserify-shim property.Bootstrap expects to find jquery on the global scope as jQuery,this is specified as shown above,it depends(an array because there can be more than one dependency) on the jquery module and expects to find jQuery module,this is specified as moduleName:globalName.You can load semantic-ui in a similar manner replacing the file to be shimmed with semantic-ui instead of bootstrap.

You can either specify your transforms in the browserify command or you can preconfigure them inside transforms within package.json.I have configured the hbsfy and browserify-shim transforms to be executed whenever I browserify my code.

 "dependencies": {  
   "backbone": "^1.1.2",  
   "bootstrap": "^3.2.0",  
   "jquery": "^2.1.3"  
  },  
  "browserify": {  
   "transform": [  
    "browserify-shim",  
    "hbsfy"  
   ]  
  },  
  "browser": {  
   "bootstrap": "./node_modules/bootstrap/dist/js/bootstrap.js",  
   "backbone": "./node_modules/backbone/backbone.js",  
   "bootstrap-validator": "./bootstrap-validator-master/dist/validator.js",  
   "bootcards": "./bootcards-master/dist/js/bootcards.js",  
   "Backbone.actAs.Paginatable": "./Backbone.actAs.Paginatable-master/src/Backbone.actAs.Paginatable.js",  
   "backbone-query": "./backbone_query-master/backbone-query.js"  
  },  
  "browserify-shim": {  
   "bootstrap": {  
    "depends": [  
     "jquery:jQuery"  
    ]  
   },  
   "backbone": {  
    "depends": [  
     "jquery:$"  
    ],  
    "exports": "Backbone"  
   },  
   "bootstrap-validator": {  
    "depends": [  
     "jquery:jQuery",  
     "bootstrap"  
    ]  
   },  
   "bootcards": {  
    "depends": [  
     "jquery:$",  
     "bootstrap"  
    ]  
   },  
   "Backbone.actAs.Paginatable": {  
    "depends": [  
     "backbone:Backbone"  
    ]  
   },  
   "backbone-query": {  
    "depends": [  
     "backbone:Backbone"  
    ]  
   }  
  }  


Wait,one last thing before you leave,how would you figure out if your shim config is working,for all you know,the file you specified for the alias might not exist,maybe you specified the wrong dependencies , a ton of things could go wrong when you specify a shim config(I have hated shims ever since I first used requirejs,they are a nessecary evil caused by differing opinions and a need to support all of them),you could add a flag to inform you of all the gory details when you run browserify:

BROWSERIFYSHIM_DIAGNOSTICS=1 browserify -d . -o js/bundle.js

Thursday, January 8, 2015

The naive developers application stack

In this modern day and age of JavaScript,things change very rapidly,first we built stuff with jQuery and maybe added a bit of underscore to add a little spice to our application. Now you've moved on, it looks like you crown a new king every other day .

Yesterday you were excited about the prospect of building MV* apps , now you are talking of doing server side javascript and then using server side modules on the client side with npm whatever that means . 

Today , you are excited about this weird angularjs thingy but I do not see the difference between onclick and ng-click and wait,are you placing that script tag in the head.Now,you have module system to manage all the module systems that you built , this is dizzying . I could only wonder about what you want tomorrow,generators to generate generators that wait for other generators perhaps.

You too once used these tools,these are the tools of the naive developer,some one who is beginning their journey into the world of JS:

(i)jQuery(duh):

Every one uses jQuery and everyone recommends that everyone else use it regardless of whether they have used it,heard of it or not. This library is intensely popular with managers as the answer to the statement , the browser cannot do that and it will not work everywhere.

jQuery came into existence because writing DOM manipulation code was incredibly hard while on the other hand,targeting DOM elements for CSS is incredibly easy(the basic selectors are simple and declarative,there are other more difficult to grok css selectors that I have shot myself in the foot with).

It weeds out browser incompatibilities and ensures that your code works across all browsers , this library plays a major role in keeping IE(6-8) alive . If there is something that jQuery cannot do , there is a plugin for it.

(ii) lodash

Functional programming is a major buzzword today in the programming universe , every language is advertising itself as a functional programming language with OO support instead of the other way , functional programming allows the programmer to use beautiful expressions with minimum code.

(iii) Q 

Promises are one of the greatest things about programming in js today,if you have not heard about them,learn about them and starting using them,Promises make your asynchronous requests easier to work with and easier to encapsulate.

(iv) Handlebars/Jade

Handlebars and Jade are templating libraries that allow you to construct custom html with data much more easily,no writing millions of lines of jQuery code that creates a table element,now you have to give the same treatment to each tr and td.You can precompile these Handlebars templates for better loading time.

(v) Browserify:

Browserify sounds like a fine idea to me,but the niggling concern at the back of my head has always been this:

     How the heck do I work with jQuery,bootstrap and certain other libraries using this build tool?

The answer for now,can only be a shim configuration transform provided by browserify-shim which transforms these modules into shimmed modules.

(vi) Express + MongoDB

This is what I use to build my servers and they rarely go work, I have found that working with express is exceptional and rather intuitive.It makes the business of server-side web development very simple,it provides you with routing which I believe is the greatest thing since sliced bread.

I am still fishing around for a good behaviour driven framework to perform tests on both node and the application.Mocha seems highly promising, the jspm and Systemjs modules seem promising but I would like to continue using Browserify for atleast a while now.

The next question for me would be:

          "To stream or not to stream"

Do I use a build tool.which one do I pick and why?There are two options available,Grunt and Gulp,I have setup everything but a proper grunt-watch task.Gulp is fairly new to me and anything I do in it blows up in my face,so grunt is the tool to go to for me.