Interactive web clients: frontend routing or backend routing?

As frontend web frameworks like AngularJS, BackboneJS and EmberJS (and ReactJS, though ReactJS doesn’t give you MVC, only V) gain prominence, a question that’s often asked and explored is — where do we specify our routing?

Frontend MVC-style JS frameworks usually come with libraries that help you define url routes.  And frontend MVC-style JS frameworks are often coupled with NodeJS, where NodeJS can act as the backend server to provide you a way to specify your url routes like Django’s urls.py does or Rails’ routes.rb or martini-go’s m.[http method GET, PUT, POST, DELETE, PATCH] do.  Typically, if we implement backend routing in NodeJS, it will be represented as such:

// ... more code above, truncate code here

var app = connect()
     .use(express.static(__dirname+"/build"))
     .use(express.static(__dirname+"/bower_components"))
     .use( function(req, res) {
var pathname=url.parse(req.url).pathname;
var localpath = path.resolve(__dirname);
switch(pathname){
    case '/register':
        getfile(__dirname+"/html/register.html", res, "text/html");
        break;
    case '/homepage':
        getfile(__dirname+"/html/homepage.html", res, "text/html");
        break;
    case '/upload':
        getfile(__dirname+"/html/upload.html", res, "text/html");
        break;
    default:
        getfile(__dirname+"/html/index.html", res, "text/html");
        break;
}
});

http.createServer(app).listen(8000, serverUrl);

which as you can see, is fundamentally analogous to the framework interfaces provided by python/django or python/flask or ruby/rails or golang/martini-go.

In short, if we so choose to use nodejs for backend routing when implementing our web client, we are essentially asking our server backend for url route definitions.

This dilutes the benefits associated with implementing a frontend-only web client because we will in fact be polling our server for a URL whenever we render a new “page” (screen).  Put it another way – would you implement an iOS or Android app that needs to ask the server which screen to transit to whenever a user needs to load a new screen?

Viewed in this context, the answer is clear — we should be using frontend routing to leverage on the full benefits provided by feature-complete MVC JS framework like AngularJS or BackboneJS or EmberJS.  This means that the end user of our web app only loads our html/js/css files once.  Dynamic data on each “screen/page” is retrieved from a REST API and has nothing to do with the “screens/pages” already implemented in the frontend, which is why all routes are *already decided* by our frontend routing the first (and-only) time your user’s web browser loads up the site.  This is also why we often refer to these type of web apps as “single page app”.

Because of frontend routing via these JS frameworks, we will see a strange hashbang symbol in our url, like this http://ourdomain.com/#/login .  Such urls are not cool in my books and I want my pretty urls!  So sad… fortunately for us, HTML5’s pushstate feature is readily available and already implemented in all these modern MVC JS framework. With a little configuration, we can have our pretty urls without the hashbang-ed urls.

Like this:-

AngularJS – http://scotch.io/quick-tips/js/angular/pretty-urls-in-angularjs-removing-the-hashtag

BackboneJS – http://zachlendon.github.io/blog/2012/02/21/backbone-dot-js-from-hashbangs-to-pushstate/

What about my SEO?

The astute reader and seasoned web developer/owner will ask a question at this point — if it’s a “single page app” that is fundamentally rendered by hashbang urls, wouldn’t our SEO be screwed?

Great question, but developers of these frameworks are seasoned web veterans…

Handling SEO is nothing but providing a way for search engine crawlers (“bots”) to navigate your website and associate content/keywords on each “url” on your website so that search engine users can find your content. Here’s a great article detailing how to “serve” content to the bots while providing the seamless experience provided by a single-page app to the human user – http://backbonetutorials.com/seo-for-single-page-apps/

Long story short, we will *still* deploy a nodejs app via phantomjs with generated “backend routing” solely to serve our bots.  As far as our human friends are concerned, they will never need to access these content or poll the server to figure out url routes.  Best of both worlds.

 

Valgrind on Mac OS X (10.9) Mavericks

On Mac OS X, the common way to write C code is to simply use the Xcode IDE.  Xcode comes with solid autocomplete functionality and has a built-in instruments app – a performance, analysis, and testing tool for dynamically tracing and profiling your program – which is absolutely critical for preserving your sanity and for revealing any mistakes you might have made that is causing memory leaks and various syntax errors in your non-trivial C applications.

The other alternative tool is, of course, the venerable valgrind.

I was curious to see if I could get valgrind working on my Mac laptop running Mavericks (10.9) as it is not yet officially supported.  Attempts to get valgrind installed via both the Macports and Homebrew package managers fail.

Fortunately, I discovered a patched branch by Frederic Germain here – https://github.com/fredericgermain/valgrind/ and and this patched branch seems to work great for Mavericks.

And this works beautifully.

# Make sure I have autoconf and automake both installed.
sudo port -v install automake
sudo port -v install autoconf
# Grab Frederic's patched valgrind on his "homebrew" branch
cd ~/work  # My usual project directory
git clone https://github.com/fredericgermain/valgrind/ -b homebrew
cd valgrind
# Because he placed VEX as a git submodule, we have to make sure we clone it too
git submodule init
git submodule update
# With VEX submodule now available, we can compile valgrind
./autogen.sh
./configure --prefix=/usr/local   # set the stage for sudo make install to place our compiled valgrind binary as /usr/local/bin/valgrind
make
sudo make install

And checking that I indeed have valgrind installed.

calvin % which valgrind
/usr/local/bin/valgrind

And now, to see valgrind in action, checking a simple C program just to verify that valgrind works as advertised.

cd ~/work/simplecprogram
make program1  # compiles my program1.c source file to program1 binary
valgrind ./program1

We should see the stdout read:-

==49132== Memcheck, a memory error detector
==49132== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==49132== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==49132== Command: ./program1
==49132==
==49132== WARNING: Support on MacOS 10.8/10.9 is experimental and mostly broken.
==49132== WARNING: Expect incorrect results, assertions and crashes.
==49132== WARNING: In particular, Memcheck on 32-bit programs will fail to
==49132== WARNING: detect any errors associated with heap-allocated data.
==49132==
Hello World.
==49132==
==49132== HEAP SUMMARY:
==49132== in use at exit: 29,917 bytes in 378 blocks
==49132== total heap usage: 456 allocs, 78 frees, 35,965 bytes allocated
==49132==
==49132== LEAK SUMMARY:
==49132== definitely lost: 0 bytes in 0 blocks
==49132== indirectly lost: 0 bytes in 0 blocks
==49132== possibly lost: 0 bytes in 0 blocks
==49132== still reachable: 4,096 bytes in 1 blocks
==49132== suppressed: 25,821 bytes in 377 blocks
==49132== Rerun with --leak-check=full to see details of leaked memory
==49132==
==49132== For counts of detected and suppressed errors, rerun with: -v
==49132== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 117 from 20)

And that’s it. Notice the warnings of course!  As I mentioned, valgrind is not offically supported beyond Mac OS X 10.7 yet.

WARNING: Support on MacOS 10.8/10.9 is experimental and mostly broken.
WARNING: Expect incorrect results, assertions and crashes.
WARNING: In particular, Memcheck on 32-bit programs will fail to
WARNING: detect any errors associated with heap-allocated data.

In any case, it is completely possible to invoke instruments from the command line as well – if you insist on writing C programs without the help of Xcode. And is a much safer bet when you are working on your production C programs.  But… that shall be a topic for another day. :-)

python virtualenv with node environment via nodeenv

Virtualenvwrapper is one of the most useful tools a python user should be familiar with.  Built on top of virtualenv, it helps us avoid a lot of redundant “code administrative” work and simplifies our 3rd party python package isolation.

NodeJS has a similar isolation mechanism and a number of such isolation tools available.

I prefer to use the nodeenv tool because it saves me the trouble of typing out long “source” commands (much like virtualenvwrapper helps me avoid typing in long “source” commands provided by the virtualenv tool).  Also, the integration with virtualenvwrapper implies that I don’t have to waste time remembering new commands to manage my isolated nodejs environment.

So here’s how it’s done. Really efficiently! (assuming of course you have installed your python virtualenvwrapper and virtualenv tools properly):

$ mkvirtualenv myproject1
$ pip install nodeenv  # This installs the nodeenv package into our new python virtualenv so named "myproject1" above
$ nodeenv -p  # This commands installs nodejs and adds new shell functions to our virtualenvwrapper shell functions
* Install node.js (0.10.12) ..
* Appending nodeenv settings to /Users/calvin/.virtualenvs/myproject1/bin/activate
$ deactivate; workon project1   # Deactivate and re-activate to ensure we load in the updated shell functions and environment

Once this is done, we are all set with project1 being our nodejs AND python isolated environment.  When we use the `npm install -g` command, we install our npm packages into our node virtual env.

$ npm install -g yo grunt-cli bower

$ yo angular
[?] Would you like to include Twitter Bootstrap?: No
[?] Would you like to include angular-resource.js?: Yes
[?] Would you like to include angular-cookies.js?: Yes
[?] Would you like to include angular-sanitize.js?: Yes

This installs the `yo`, `grunt-cli` and `bower` tools directly into our node virtual environment and using `yo angular` we easily scaffold out a new angularjs project.

A quick peek at our ~/.virtualenvs/myproject1 directory shows us the directory structure that includes python packages and npm packages.


$ cd ~/.virtualenvs/myproject1

$ tree -L 2
.
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── activate_this.py
│   ├── bower -> ../lib/node_modules/bower/bin/bower
│   ├── easy_install
│   ├── easy_install-2.7
│   ├── get_env_details
│   ├── grunt -> ../lib/node_modules/grunt-cli/bin/grunt
│   ├── istanbul -> ../lib/node_modules/istanbul/lib/cli.js
│   ├── karma -> ../lib/node_modules/karma/bin/karma
│   ├── node
│   ├── nodeenv
│   ├── npm -> ../lib/node_modules/npm/bin/npm-cli.js
│   ├── pip
│   ├── pip-2.7
│   ├── postactivate
│   ├── postdeactivate
│   ├── preactivate
│   ├── predeactivate
│   ├── python
│   ├── python2 -> python
│   ├── python2.7 -> python
│   └── yo -> ../lib/node_modules/yo/bin/yo
├── include
│   └── python2.7 -> /opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
├── install.cfg
├── lib
│   ├── dtrace
│   ├── node_modules
│   └── python2.7
├── share
│   └── man
├── src
│   └── node-v0.10.12
└── tags

That’s it.