Posts Tagged node.js

HTTP Basic Authentication for Sails.js 0.9.x using Passport

One of my initial excursions into Sails.js territory:

https://gist.github.com/adityamukho/6260759

, , , ,

Leave a comment

Berserker is now available on NPM Registry

I had posted a while back about a web-based front-end to aria2c that I started building, primarily as an exercise in learning Node.js. While it has been functional and available on GitHub for some time, I now have the pleasure to announce that it is now available directly through the NPM Registry.

Happy downloading!

, ,

Leave a comment

Getting Serious with JavaScript

My recent decision to teach myself Node.js has turned out to be a good one. It runs on Google Chrome’s V8 JS engine and leverages JavaScript’s event model to provide non-blocking IO, allowing for fast, responsive applications that scale extremely well, even on low-end hardware.

Being a web developer for a few years now, I was already familiar with basic JavaScript, so the learning curve wasn’t greatly steepened on account of having to learn a whole new language. I did have to make a quantum leap in my outlook towards JS as a serious programming language though – what once used to be the silent underdog, used for writing a few onClick event handlers, and for sprinkling AJAX calls all over web pages, has now come into its own. Server-side JS programming really requires a much deeper and thorough understanding of the language and its associated design and programming paradigms than ever a alert(‘Your password must contain at least 6 numbers and 4 Egyptian hieroglyphs’) has called for. With widespread adoption in both server-side and client-side programming, JavaScript is now a true isomorphic language.

Needless to say, my JS knowledge base required a few upgrades before I could put together anything smarter than a ‘Hello World’ responder. Said upgrades, among other excellent sources, I have found here, here, here along with the JS object graph learning trail (part 1, part 2 and part 3). In fact, most of How to Node is a must-read if you’re planning on serious Node programming.

But this post is not just about my experience learning server-side JS. In the process of upgrading my overall web development repertoire, I’ve had to undergo quite a steep ramp-up on client-side JS technologies as well…

Not least of which was AngularJS. Ran into this fellow while looking for a good client side toolkit for building RIAs, especially one that was best suited for single page applications. Back then, my feet were firmly planted on Java turf (in spite of it showing obvious signs of age), and I was looking for a client library that would work well with Java on the server side. Did a few rounds of GWT, ZK, Vaadin and kin until I realized that all of these frameworks incurred a significant learning curve, tedious integration points to cooperate with custom Spring stacks, limited and buggy IDE support (among open-source IDEs, including STS and IDEA community edition; don’t know about IDEA Pro), and no small amount of code bloat on the server side in spite of auto-magic scaffolding and suchlike voodoo. Servers would have to carry out a lot of deeply nested processing to build the views for presenting to the client (esp. in frameworks that took the ‘pain’ of writing client-side javascript away from developers, by auto-generating it from java code).

The biggest problem still, was the lack of flexibility, in spite of all the automation and scaffolding (or perhaps because of it), in building a custom UI to one’s exact liking (esp. with dynamic scaffolding, where you lose significant control over the finally generated DOM). Including client-side styling libraries like Bootstrap would require jumping through increasingly tight hoops in order to make the auto-generated templates adhere to the specific DOM and CSS requirements dictated by such libraries.

I don’t remember if it was by chance, or deliberate intent (esp. since I was previously aware of jQuery UI) that my search led me to the discovery of pure client-side presentation technologies. The first one I tried (and was amply impressed by), was Knockout. This was really an ‘Aha!’ moment for me. One go at their live tutorial was enough to convince me of the potential of JavaScript to completely take over the client-side presenting/rendering business, greatly simplifying things on the server side, which now need bother about little more (w.r.t. presentation) than furnishing the HTML template and the JSON data upon which the JS framework could go to work.

Having discovered this entirely new (to me) method of structuring webapps, which basically addresses all the pain points mentioned above, I went about hunting for other similar offerings in the browser space; but by now I was convinced of JavaScript’s ability to be much more than just an errand boy.

As of today, I’m still delving deeper into the fascinating world of server-side JS runtimes, the accompanying middleware (Connect and Express being among the biggest names here), while also being repeatedly amazed by the power of modern client-side frameworks. The JS landscape is already incredibly expansive, and continues to grow at a frightful rate, as each day heralds the launch of several new libraries, frameworks and tools that make JS programming all the more exciting and enlightening.

My journey of exploration has already started bearing fruit, and has empowered me to give back to the wonderful open source community (JS or otherwise) that I have received so much from. My current efforts are focused on building a JS-based e-commerce platform, and I am confident I have selected the right platform for the necessary pace of development and superior performance that I demand of the product-to-be.

, ,

1 Comment

An advanced web-based frontend for Aria2-JSONRPC

An advanced web-based frontend for Aria2-JSONRPC

I’m building a full-featured web-based frontend to the powerful CLI download manager Aria2. It is still work in progress but already supports HTTP(s)/FTP/Magnet downloads.

Screenshot

The ‘Downloads’ Page

It would be great to find some early adopters who would give it a try and share their feedback.

UPDATE: Berserker is now available for download through the NPM Registry!

, , , ,

2 Comments

Minifying + Compressing an AngularJS App

This short tutorial demonstrates how to prepare an AngularJS app for deployment to a static web server, with all the bells and whistles needed to score an A on YSlow.

Key Assumptions

  1. Your dev setup is on Linux, or other Bash-compatible. (Build script written for Bash.)
  2. You use Git for SCM. (The build script will use git for some operations. Feel free to alter the script, and get rid of this dependency.)
  3. The app is structured as recommended by the angular-seed project. (Build script expects certain folders to be present at specific locations. You can adapt it to your project structure.)

Dependencies

Go grab the following:

  1. YUI Compressor
  2. Git
  3. Gzip (Installed by default on most *NIX systems. Pull from distro repos otherwise.)
  4. Node.js (For testing stuff on your localhost. Not required if you have/prefer some other server for delivering static content.)
  5. Stomach for shell scripts

Prologue

I wanted to split my web application into two distinct components:

  1. A client-side, JS-driven presentation layer.
  2. A lightweight, REST-based backend.

I’ve had to sort out a lot of issues to get both to cooperate while running on different servers on different domains, use digest-based authentication instead of cookies (REST is stateless), and so on, but that’s another post. This one focuses on efficiently delivering the UI portion – HTML + CSS + JS + Media – which from a server POV is static content.

Preparing AngularJS Scripts for Minification

The AngularJS docs provide some information on how to prepare controllers for minification here. Quoting from the page:

Since angular infers the controller’s dependencies from the names of arguments to the controller’s constructor function, if you were to minify the JavaScript code for PhoneListCtrl controller, all of its function arguments would be minified as well, and the dependency injector would not be able to identify services correctly.

PhoneListCtrl is part of the angular-phonecat application, used for driving the on-site tutorial.

Basically, every controller defined by your application needs to be explicitly injected with whatever dependencies it has. For the example above, it looks something like:

PhoneListCtrl.$inject = ['$scope', '$http'];

There is one more way defined on the site, but I prefer the method above.

However, this is not enough to get minified scripts working right. YUI Compressor changes closure parameter names, and this doesn’t go down well with Angular. You need to use inline annotations in defining custom services. You can find a usage example here.

Additionally, you can collate all content from controllers.js, directives.js, services.js and filters.js into app.js to reduce the number of calls made to the server.
Don’t forget to modify your index.html / index-async.html to reflect this change.

The Build Script

If you’re sticking to the folder structure provided by angular-seed, you’ll have an app folder in your project root. Adjacent to this, create a build folder to contain the minified and compressed output files generated by the build script. You can tell git to ignore this folder by adding the following line to .gitignore:

/build/*

You can put your build script anywhere you like, and run it from anywhere in the project folder. I have put it inside the conveniently provided scripts folder.

#!/bin/bash

ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccgreen=$(echo -e "\033[0;32m")
ccend=$(echo -e "\033[0m")

exit_code=0

cd "$(git rev-parse --show-toplevel)"

#Minify
echo -e "$ccyellow========Minify========$ccend"
for ext in 'css' 'js'
do
    for infile in `find ./app -name *.$ext |grep -v min`
    do
        outfile="$(echo $infile |sed 's/\(.*\)\..*/\1/').min.$ext"
        echo -n -e "\nMinifying $infile to $outfile: "
        if [ ! -f "$outfile" ] || [ "$infile" -nt "$outfile" ]
        then
            yuicompressor "$infile" > "$outfile"
            if [ `echo $?` != 0 ]
            then
                exit_code=1
                echo -e "\n$ccred========Failed minification of $infile to $outfile . Reverting========$ccend\n" >&2
                git checkout -- "$outfile" || rm -f "$outfile"
            else
                echo $ccgreen Success.$ccend
            fi
        else
            echo $ccgreen Not modified.$ccend
        fi
    done
done

#Compress / Copy
echo -e "\n\n$ccyellow========Compress / Copy========$ccend\n"
for infile in `find ./app -type f -not -empty`
do
    filetype="$(grep -r -m 1 "^" "$infile" |grep '^Binary file')"
    outfile="./build/$(echo $infile |cut -c7-)"

    mkdir -p $(dirname "$outfile")
    if [ ! -f "$outfile" ] || [ "$infile" -nt "$outfile" ]
    then
        if [ "$filetype" = "" ] #Compress text files
        then
            echo -n -e "\nCompressing $infile to $outfile: "
            gzip -c "$infile" > "$outfile"
        else #Copy binary files as is
            echo -e -n "\nCopying $infile to $outfile: "
            cp "$infile" "$outfile"
        fi
        if [ `echo $?` != 0 ]
        then
            exit_code=2
            echo -e "\n$ccred========Failed compress / copy of $infile to $outfile . Reverting========$ccend\n" >&2
        else
            echo $ccgreen Success.$ccend
        fi
    else
        echo -e "$infile -> $outfile: $ccgreen Not modified.$ccend\n"
    fi
done

echo -e "\n$ccyellow========Finished========$ccend"
exit $exit_code

Once you run this script, every app/file.[css | js] would have a working copy at build/file.min.[css | js]. Every other file in the app folder will be either:

  1. compressed and copied (name unchanged) into the build folder if it is a text file, or
  2. simply copied into the build folder if it is a binary file (like an image).

Your CSS and JS references need to be updated to their corresponding min versions in index.html / index-async.html.

Now that you’ve got a compressed, minified version of your app in the build folder, you can deploy it to any static server. But you do need to set your HTTP response headers properly, or the browser WILL show garbage. Most importantly, any compressed content must be served with the HTTP response header:

Content-Encoding: gzip

Additionally, for every file that is static content, it makes sense to set a far future date using an Expires header similar to the following:

Expires: Thu, 31 Dec 2037 20:00:00 GMT

The NodeJS web-server.js Script

The contents of the build folder are technically ready to be uploaded to any web server, but you will probably want to run the app from your localhost to first check if everything works fine. The built-in web-server.js is very useful to quickly launch and test your app, but it needs a few mods in order to serve the compressed content from the build folder correctly. The Content-Encoding header is sufficient to render the page correctly, but if you’re a stickler for good YSlow grades even on your localhost, you will want to add the Expires headers as well. Search for the following response codes in your web-server.js and add the lines listed below:

  1. 200 (writeDirectoryIndex), 500, 404, 403, 301:
    'Expires': 'Thu, 31 Dec 2037 20:00:00 GMT',
    
  2. 200 (sendFile) (After var file = fs.createReadStream(path);):
    var fileType = StaticServlet.MimeMap[path.split('.').pop()];
    var contentType = fileType || 'text/plain';
    res.writeHead(200, {
        'Content-Type': contentType,
        'Expires': 'Thu, 31 Dec 2037 20:00:00 GMT',
        'Content-Encoding': ((path.indexOf('./build') === 0) && ((contentType.indexOf('text') === 0) || (contentType.indexOf('application/javascript') === 0))) ? 'gzip' : ''
      });
    

That’s it! Now when you run the web-server.js, all content from the build folder will be correctly served with the ‘gzip’ header (unless it is a binary).

, , , , ,

2 Comments

%d bloggers like this: