May 21 2009

Ultimate JavaScript minification

Category: Ideas, JavaScript, UtilitiesMatjaž Lipuš @ 10:00 am

This is a guest post by Matjaž Lipuš, a social web geek, front-end web developer and semantic web enthusiast.

After developing some fat client applications using JavaScript frameworks I noticed how some code constantly repeats, making application footprint even bigger than necessary.
A while ago I (once again) stumbled upon article about helping the YUI Compressor. Article is great and in large client side applications could really make a difference in final footprint considering these tips. I think this should be automated as much as possible, so I extended a list of this tips which could be fully automated. And here comes in the YUI Compressor (YUIC).
I am using YUIC for code minification. I also contributed some fixes and suggestions to the author – Julien Lecomte. Those were implemented in past versions. YUIC is a great tool for code minification and munging. I believe it can be further extended and improved generating even smaller output. So here are my tips how to achieve this, ordered by complexity.

Concatenate static strings with +

If you have a big chunk of text to insert into page you would probably split it into multiple lines and making multiple strings. YUIC already has functionality concatenating static strings into one. So code like this:

var x = "This is " +
        "some text";

becomes:

var x="This is some text";

Don not use arrays for this, because YUIC cannot tell you are actually concatenating strings.

Variable declarations at the beginning of the function

Scope in JavaScript is per function. So if you declare a variable twice in the same function, second time variable is just overridden with new value. As JSLint suggests you should declare all variables at the beginning of the function. Looking at this from minification view this means only one var statement! So instead of:

function iterate(array) {
    var result = "";
    for (var i=0, len=array.length; i<len; i++) {
        var el = array[i];
        result += el + ",";
    }
    return result;
}

write:

function iterate(array) {
    var result = "",
        i, len,
        el;
    for (i=0, len=array.length; i<len; i++) {
        el = array[i];
        result += el + ",";
    }
    return result;
}

You should note when declaring global variables there is no need for var statement at all.

This as local variable

Writing serious JavaScript code means writing object-oriented code. In JavaScript we access object members in conjunction with this keyword. This means a lot of this keywords.

Person.prototype.getInfo = function()
{
    var result = "",
        i, len;
    for (i=0,len=this.length; i<len; i++) {
        result += this[i].name + " " + this[i]. surname + " - " + this [i].age;
    }
    return result;
};

Assigning this to a local variable means YUIC can munge local variable to a 1-3 letters which means smaller footprint.

Person.prototype.getInfo = function()
{
    var x = this,
        result = "",
        i, len;
    for (i=0,len=x.length; i<len; i++) {
        result += x[i].name + " " + x[i]. surname + " - " + x[i].age;
    }
    return result;
};

You should note local variable must be declared first, as we could access members of this object in the following variables declaration/assignment.

Person.prototype.getInfo = function()
{
    var x= this,
        result = "",
        i, len = x.length;
    for (i=0; i<len; i++) {
        result += x[i].name + " " + x[i]. surname + " - " + x[i].age;
    }
    return result;
};

You should also note using this as local variable is only reasonable when this keyword occurs at least two times per scope, but that is most of the time.

Shorten numbers

Although this seems to be strange it is simple to trim leading zero from decimal numbers. So instead of:

var n1 = 0.1,
    n2 = -0.1;

you should write

var n1 = .1,
    n2 = -.1;

Common strings

As with JavaScript frameworks and it’s hash style configs there is a lot of string repetition.

var form = new MyForm({
    id: "form",
    items: [{
        type: "text",
        cls:  "blue",
        name: "name"
    }, {
        type: "text",
        cls: "blue",
        name: "surname"
    }]
});

This code can be minified (in a inner scope) as:

var textString = "text",
    blueString = "blue",
    form = new MyForm({
    id: "form",
    items: [{
        type: textString,
        cls: blueString,
        name: "name"
    }, {
        type: textString,
        cls: blueString,
        name: "surname"
    }]
});

A special caution must be given to a strings declared as variables as they can be changed. So we cannot use this variable as a constant. These two strings should be separated into two variables unless we are sure value has not been changed until constant string usage.
We could go even further by moving common strings to outer most scope which uses this string and accessing it in inner scopes with closures and even further replacing substrings (in this case »name«). This raises a question about performance penalties doing string concatenation.

Repeating access to object members

function focusInput()
{
	if (this.msgInput) {
		this.msgInput.focus();
	}
}

this could without any problem been written as

function focusInput()
{
	var msgInput = this.msgInput;
	if (msgInput) {
		msgInput.focus();
	}
}

Shorten object’s member access

JavaScript libraries have a nice namespace convention, but in a large usage of library you get a lot of code repetition.

var store  = new Lib.data.Store(),
    record = new Lib.data.Record();
store.add(record);

We can see a common namespace is Lib.data which can be shorten by assigning to a variable

var Data   = Lib.data,
    store  = new Data.Store(),
    record = new Data.Record();
store.add(record);

There could even be further improvements if we are dealing with (static) object which does not have this key word in the function. Good example is the utility function JSON.stringify(), which can be assigned to a local variable.

var toJSON  = JSON.stringify,
    result1 = toJSON(obj1),
    result2 = toJSON(obj2);

Shorten object’s member names

While using namespaces is good in an organizational way it means a lot of code for just accessing object. The idea is to shorten object’s member names. So instead of

function Person(name, surname)
{
    this.firstName = name;
    this.lastName  = surname;
}
Person.prototype.getFullName = function()
{
    return this.firstName  + " " + this.lastName;
};

code looks like

function Person(name, surname)
{
    this.a = name;
    this.b = surname;
}
Person.prototype.c = function()
{
    return this.a + " " + this.b;
};

This is only reasonable for automated process, although keeping short member names can also save a lot of bytes.
You should keep in mind that you must replace member access in all places, this means where they are defined (set) and used. You also cannot shorten reserved members such as Array’s length or documents getElementsById.
So a good idea would probably be keeping a white list of members which should (not) get munged.

I was already doing some work in YUIC about variable declarations at the beginning of the function, shorten numbers and common strings, but it is not 100% stable, although I successfully minified some of the JS libraries.
Also I did not measure any performance penalties of these tips, but it would be interested to see some.
You should note that this would best perform if code is also JSLint compliant.

Tags:


May 16 2009

A proposal for symbiosis between Wolfram Alpha and Wikipedia

Category: Ideas, UncategorizedAleksander Kmetec @ 9:30 pm

Attention, please!

Wolfram Alpha is not a Google killer!
Wolfram Alpha is not a Wikipedia killer!
Wolfram Alpha does not want to dismember any company and bathe itself in its blood!

Please ignore unimaginative claims made by linkbait authors. Let’s forget the 1999’s prehistoric “me kill” mentality and focus instead on more peaceful opportunities. We now live in the age of mash-ups, so here’s my modest proposal for symbiosis between Wolfram Alpha and Wikipedia.

The opportunity for symbiosis comes from their different strengths. Wolfram Alpha’s FAQ section gives a very clear description of how it compares to Wikipedia:

Wikipedia gives you pages of narrative about topics. Wolfram|Alpha computes answers to specific questions you ask, just giving facts, not narrative. Wolfram|Alpha often includes sidebar links to Wikipedia.

Wikipedia describes a concept; Wolfram Alpha gives you the ability to try out that concept in practice.

And because everything needs a car analogy…
Wikipedia is like a car magazine and Wolfram Alpha is like a car simulator. You can open a magazine and read more about a car you just took for a virtual test drive, or start with the magazine and go for a ride in a car you just read about.

You can see in the above quote that one-way links from Wolfram Alpha to Wikipedia already exist. What’s still missing are connections from Wikipedia to Wolfram Alpha, which might one day look like this:

A hypothetical Wolfram Alpha / Wikipedia mash-up. Click for full size.

A hypothetical Wolfram Alpha / Wikipedia mash-up. Click for full size.

There you have it. Wolfram Alpha and Wikipedia can not olny coexist peacefully, they can help each other. No need to argue about who is going to kill who.

Tags: , , , ,


May 07 2009

The future is in the ability to ignore

Category: UncategorizedAleksander Kmetec @ 7:18 am

“It’s time to get completely off RSS and switch to Twitter. RSS just doesn’t cut it anymore.”, says Steve Gillmor in his Techcrunch post titled “Rest in Peace, RSS“.

While most commenters see his rant as a sign of the old man slowly losing his mind, it is also a sign of another thing: filter failure. Filter failure is what causes information overload and was also the topic of Clay Shirky’s Web 2.0 Expo keynote in NYC, which you can watch below:

So what’s happening here?

RSS readers are partially recreating the conditions which make reading email such a chore. They require you to check them every so often, read all the messages and make sure that the number of unread messages goes down to zero and stays there! But it never does. Every time you check your reader, there are new messages waiting and demanding your attention, even though they don’t really need it. Posts worth reading are lost among dozens which are not. After a while you start drowning in a flood of content you’re not interested in, you become overloaded and you don’t even bother unsubscribing from the feeds, you just stop checking your RSS reader altogether.

You switch over to twitter where all the links you see are already pre-filtered by other people. Think about it – in order for a link to end up in your Twitter stream, somebody must have already read the article and decided it was worth sharing. In addition to this, your previous experience tells you whose links are worth clicking and whose not. And yes, there is a new lump of messages waiting for you every time you log into Twitter and their number is very likely to be overwhelming, but Twitter has no “unread count” which would force you to check every single tweet and doesn’t have a “mark all as read” button which would make you feel like you were missing something every time you used it. It allows you to check as many messages as you want to and doesn’t demand anything from you.

Or as Stephen Baker puts it:

On Twitter, each of us can recommend a link. If you have 500 followers, maybe 50 of them see it. Maybe five of them take a look. Let’s say two appreciate it. The other three may be less likely to open your links in the future. Maybe one will “unfollow” you. But that’s ok. Each of us finds our own audience. But the key is that there’s little guilt or obligation associated with Twitter. It’s a managed pool of serendipity.

In some cases filters alone are no longer enough to avoid information overload. We also need a way of ignoring what can safely be ignored.

Tags: , , , , , ,


May 04 2009

On named parameters

Category: IdeasAleksander Kmetec @ 5:07 am

Here’s a proof that quitting your job and not working on anything for two months is not good for you: I just spent two days pondering why named function parameters are loved by coders and considered an important part of many programming languages while named parameters in URLs are considered to be ugly, harmful and one of the leading causes of scurvy. Developers will even find a way to emulate named function parameters in languages which don’t support them by default while at the same time they will try their best to make all the parameters in URLs of their websites strictly positional. It makes everyone look a bit confused and bipolar, if you ask me.

Here’s a quick overview of the situation.

Named parameters in URLs: BAD
http://domain.com/list?type=fruit&page=1&items=20

Positional parameters in URLs: GOOD
http://domain.com/list/fruit/1/20

Named parameters in function calls: GOOD
foo.list(:type => “fruit”, :page => 1, :items => 20)

Why is this so? It might have more than just a little bit to do with the fact that coders spend a lot of their time reading, writing and modifying function calls, while URLs are only rarely modified by anyone (or even read, for that matter). The need to modify URLs is so rare in fact that many security holes exist only because developers never even remotely considered that someone might insert an unfriendly value into one of the parameters. It makes sense then that if URLs are only meant to be looked at, to make them short and pretty and clean of any characters which make them appear as if they’ve been involved in an explosion at the ASCII factory.

Why then is the URL, this unfriendly sequence of characters, still presented as a fully editable value? Is it really not possible to turn it into anything more than a barely readable “you are here” sign?

Microsoft managed to do something interesting with the way directory paths (URL’s distant relatives) are displayed in Vista and Windows 7: each directory is a separate button and clicking any one of them takes you directly to that directory.

Windows explorer in Vista

Two different ways of displaying the same directory path

Couldn’t something similar be done for URLs? Here’s my suggestion: make it easy to experiment with different parameter values. Hide all the “noise” characters. Turn each key/value pair into a button and offer alternative values when somebody clicks them.

Location bar

Now, this might not catch on with your average Joe Streetperson, but it does look like it could be useful to developers when they are testing a website or a web service which returns different XML/JSON based on parameter values.

Think of it as Intellisense for the location bar.

Tags: , , ,