Topic: javascript

Optimizing the Google +1 button for speed

If you’re like most bloggers and site owners, you’ve probably already added or are planning to add the new Google +1 button to your website, to go along with the Twitter and Facebook buttons. Having implemented the +1 button I’ve found that the script takes a long time to load, and does not even load if you’re on an iPhone or iPad. This actually comes as a shock to me considering Google itself is a huge advocate of page speed improvements. The file (plusone.js) is 4 KB (before gzipping) and gets assigned a short expiration time of only 60 minutes by Google. Thankfully the script is gzipped and is only semi-minified, but it still takes a new uncached hit about 1.26 seconds to complete. Most of this time is spent in either the Blocking or Waiting stages, which might have something to do with it being served from a secure server. The decision to load the file over HTTPS by default is a bit baffling to me, especially since the handshake is historically slower. Unless sensitive information exists in the JS code which could be another interesting topic. Google has been doing some work on SSL FalseStart in Chrome to alleviate SSL latency and it seems their goal is to eventually serve all their services securely. Plusone.js then loads a second much larger js file from plusone.google.com also over SSL which comes in at about 57 KB (before gzipping). This file tacks on another 1.17 seconds to the completion time for the +1 button.

After seeing how slow the Google +1 button loads and how it can actually degrade your website’s overall pageload time, I started looking around for answers. First of all, I found that I’m not the only one complaining about the issue. Numerous others have started to point out the speed issues with the +1 button. My second thought was to perhaps remove the button from the site, although considering the effect the +1 button has on your website’s ranking that would mean less love from Google.

So what’s a developer to do? If we keep the button on our site, overall pageload times spike. But if we remove the button, or not add it, we might lose out on a potential piece of the social voting pie which most believe affects your search performance.

So here are my techniques for making Google +1 button load faster, or at least not slow down your site. Interestingly enough these techniques are the same set of tips and tricks that Google’s own Page Speed recommends for webmasters.

1) Save a step, Use Https

Make sure you use the HTTPS protocol in the URL for the JavaScript source, as the original version of the button snippets given out by Google included the HTTP version http://apis.google.com/js/plusone.js which just does a redirect to https://apis.google.com/js/plusone.js This issue has since been corrected by Google when you use Google’s +1 button generator site.

2) Don’t load the script on Mobile devices

As stated by Google, currently the Google +1 button does not support mobile devices like the iPhone, iPod touch, iPad, or Android. This means if you have the button code on a mobile site you’re basically wasting HTTP connections and adding extra weight to your site’s throughput. To get around this fact you need to write a little utility function in JavaScript that sniffs the userAgent for unsupported devices, and only makes a call to the script if your client is not one of those devices.
For example in the case of an iPhone and iPad website, you would do something like this:

function isMobileUser(){
  return (/iphone|ipod|ipad|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()));  
}
if(!isMobileUser()){
	//include the plusone.js code here
}

3) Load the plusone.js script asynchronously

HTML 5 has introduced the ability to load scripts asynchronously allowing the rest of the page to load independently of potential bottlenecks. This feature is actually already in use for the Google Analytics code. Keep in mind that only Chrome and Firefox 3.6 and above support the async feature at this time. But it does not hurt your non-supporting browsers in any way so it’s safe to use. Here’s the code that combines the check for unsupported mobile browsers from before to load the +1 button script asynchronously. Note that since this code is loaded asynchronously it doesn’t matter if you put the call in the footer or header.

function isMobileUser(){
  return (/iphone|ipod|ipad|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()));  
}
if(!isMobileUser()){
// create a new script element in the DOM
var gp1script = document.createElement('script');
// set it's type attribute, not really needed in HTML 5 but just to be safe
gp1script.type = 'text/javascript';
// set the HTML 5 attribute of async to true for the script tag
gp1script.async = true;
// set the source attribute to the https version of the google pluseone code
// change this to your own server path if you are cosidering using option 4 below
gp1script.src = 'https://apis.google.com/js/plusone.js';
// add the new script tag to the head or body of the page
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(gp1script);
}

You would then place the tag where you want the +1 button to render, which since it is a proprietry tag will just be ignored if the script is not present on your page.

<g:plusone></g:plusone>

If you’re not comfortable with the tag, you can also use an HTML 5 version to render the +1 button on your site, which uses a css class of g-plusone and sets attributes as needed. For example you can display a standard +1 button with counts using this HTML 5 tag.

<div class="g-plusone" data-size="standard" data-count="true"></div>

Note that you can also place multiple +1 buttons on a single page. For example you might have a +1 button that directs its vote to your main parent homepage like so:

<g:plusone href="http://www.your_tld.com/></g:plusone>

4) Host the plusone.js file yourself

This option has been suggested by some users, although I personally argue against it just because you’ll be responsible for continuously monitoring changes and updating your version. The big benefit here is avoiding that dreaded HTTPS server, but keep in mind the script still will make that second call to load the plusone library so you’re still not home free. Only go this route if you’re seriously considering a site improvement and are willing and capable of pushing out updates to your version of the script. I’m sure the Google +1 team is making lots of changes and adding bug fixes which you will miss out on if you forget to update the script on a daily basis. In the extreme case you could perhaps write a program that downloads the latest version of the script from Google’s servers and updates your version on a daily basis, but then again this becomes a new task to keep an eye on.

Hope this helps and let me know if you have other tips and or feedback regarding these ideas. For more details be sure to read the +1 button API page.

Wishlist: Browsers contain major JavaScript libraries in memory

Let’s face it, without JavaScript the web would be a boring place. Unless you roll your own, well you need to use a library of some sort, and in most cases you need more than just one library to achieve your intended user experience.

Performance optimizations aside, and even if you concatenate all your JS files into a single file, you still have to load the library into the browser after the request has been made, and you can’t do anything with it until that has finished loading.

Wouldn’t it be so great if the browser had a copy of YUI or jQuery or Dojo or Prototype or GWT in memory at all times? Then your library using decision would not be influenced by the size of the library but by its speed and performance, and perhaps features and functionality provided. I mean you don’t go loading new fonts and new plugins every single time you go to a new page right? Then why do we have to download the same 5 or 6 JS libraries over and over all day long as we browse the web? And if this was an option how many companies would spend time rolling out their own rather than adopting one?

I understand there would be tons of politics involved and it will probably never happen in a million years but it is worth a try. Perhaps at least a FF only version could be done through an add-on that loads the latest major version of all these libraries and checks for updates on startup, similar to how other plugins get updated in FireFox today. The browser would have to namespace the libraries to avoid confusion. Developers would then just do a test to see if the browser has a required library in memory, and if not then make a server call for it as a fail safe.

It would take lots of collaboration and standardization. JavaScript was the sleeping giant that was brought to center stage with the success of frameworks and libraries that have fueled its standardization and resulting wider adoption. Why not give those libraries some credit and package them into your browsers?

Google Chrome First Impressions

Yet another browser? Well here we go again. Let’s take a look at Chrome and see what it has to offer. The download page is located here. The installer for Windows XP is only 474KB! You can watch the press conference video about Google Chrome or read the Google Chrome Book in the meantime.

What we knew so far about Chrome

  • Uses V8 JavaScript engine which supports Classes and compilation. There is a V8 JavaScript benchmark suite that gives FireFox 3 a score of 83, while giving Chrome a score of 1213! Safari 3 gets a score of 128. Judging by this alone, V8 blows away the competition.
  • Uses Webkit rendering engine.
  • Tabs run as independent processes which can be managed.
  • Lots of other features.

First Impressions

  • Installation was a breeze and imported FireFox settings.
  • No status bar, You only see the status bar when you hover over a hyperlink.
  • The Task Manager (Shift + Escape) updates in real time and shows memory, CPU and network usage for each tab, each plugin, and the main Chrome process separately. There is also a link to Stats for Nerds with lots more gritty info.
  • The Flash plugin is extremely CPU usage intensive and causes sluggishness when scrolling. I just loaded a popular flash website and noticed my machine came down to a near halt. It seems to happen more with Flash files that contain infinite loops, using as much as 70% of the CPU.
  • The built in JavaScript console looks like a combination of FireBug and Web Inspector.
  • There is a built in JavaScript Debugger (Alt + `)
  • Passes the Acid 2 test.
  • Chrome gets a score of 78 on the Acid 3 test, which is higher than FireFox 3 at 57, Safari at 72, and Opera at 45.
  • Omnibar – this is the URL/location bar in Chrome that has some fuzzy logic built in to suggest “smart” autocompletes. This is the current order of the drop down in the auto complete list. There seems to be no way of changing this ordering as of now. Would be nice to be able to customize them.
     

     

    1. Search Google for FOOBAR
    2. FOOBAR/ (I’m not sure how useful this one is really)
    3. Link to the FOOBAR Wikipedia page
    4. Link to I’m Feeling Lucky URL for term FOOBAR. This item gives you the ability to search within the URL. For example if you type in Amazon in the Omnibar and select the amazon.com option using the down arrows, you will see “Press Tab to Search Amazon”. See below instruction on implementing this search functionality for your website.
    5. Search Google for FOOBAR ANOTHER TERM
    6. Search Google for FOOBAR ANOTHER TERM
    7. A page in your history pertaining to FOOBAR
    8. Link to history search for pages about FOOBAR

Cool Developer related stuff in Chrome

Google Chrome User Agent String:

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.X.Y.Z Safari/525.13.

Chrome has a menu option called “Create application shortcuts…” that uses Google Gears to create a shortcut to your webapp. Users can choose to place the shortcut to your webapp on their Desktop, on the Start menu and even the Quick launch bar in Windows. This is a pretty powerful feature. When a user clicks this icon, Chrome opens up without the Omnibar, and your website will appear in an “Application” format. You can customize how Chrome creates these shortcuts using meta tags. These tags are named: application-name, description, application-url, and shortcut icons in both 32×32 or 48×48 formats. The favicon is used if not specified. For example you can use the following HTML code in the head of your document. Note that with the Mozilla added support which is used in Chrome, you can use any supported graphic format as your favicon, and not just the old school favicon.ico file.

<head>
  <meta name="application-name" content="Gmail"/>
  <meta name="description" content="Google's approach to email"/>
  <meta name="application-url" content="http://www.gmail.com"/>
  <link rel="icon" href=gmail_32x32.png sizes="32x32"/>
  <link rel="icon" href=gmail_48x48.png sizes="48x48"/>
</head>

To open a new tab from your webapp in a separate process using JavaScript you can do this in Chrome.

var w = window.open();
w.opener = null;
w.document.location = "http://differentsite.com/index.html";

Chrome lets users search your website from its ominbar. To enable and include your website’s search in Chrome you have to create an OpenSearch description document (OSDD).
For example you can create something like this:

<?xml version="1.0" encoding="UTF-8"?>
 <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
   <ShortName>Web Search</ShortName>
   <Description>Use Example.com to search the Web.</Description>
   <Tags>example web</Tags>
   <Contact>admin@example.com</Contact>
   <Url type="application/atom+xml"
        template="http://example.com/?q={searchTerms}&amp;pw={startPage?}&amp;format=atom"/>
   <Url type="application/rss+xml"
        template="http://example.com/?q={searchTerms}&amp;pw={startPage?}&amp;format=rss"/>
   <Url type="text/html" 
        template="http://example.com/?q={searchTerms}&amp;pw={startPage?}"/>
   <LongName>Example.com Web Search</LongName>
   <Image height="64" width="64" type="image/png">http://example.com/websearch.png</Image>
   <Image height="16" width="16" type="image/vnd.microsoft.icon">http://example.com/websearch.ico</Image>
   <Query role="example" searchTerms="cat" />
   <Developer>Example.com Development Team</Developer>
   <Attribution>
     Search data Copyright 2005, Example.com, Inc., All Rights Reserved
   </Attribution>
   <SyndicationRight>open</SyndicationRight>
   <AdultContent>false</AdultContent>
   <Language>en-us</Language>
   <OutputEncoding>UTF-8</OutputEncoding>
   <InputEncoding>UTF-8</InputEncoding>
 </OpenSearchDescription>

Fore more tips read the Google Chrome FAQ for web developers page.

ps. Don’t use the Google gears Chrome download page which gives a JavaScript error!

_GU_SetupOneClick is not defined
onload(load )

JavaScript Arguments

The arguments object in JavaScript is a local variable in any function that provides some nice features we can use in our code. Here is the list of its properties and related properties of the Function object.

arguments itself returns an object that looks like an array (but not really an array) of the arguments passed to the function.

Prior to JavaScript 1.4 the Function object also had a similar arguments property, which is now deprecated.

However the Function object comes with a few other useful properties that we can still use to get argument related data.

function callTaker(a,b,c,d,e){
  // arguments properties
  console.log(arguments);
  console.log(arguments.length);
  console.log(arguments.callee);
  console.log(arguments[1]);
  // Function properties
 console.log(callTaker.length);
  console.log(callTaker.caller);
  console.log(arguments.callee.caller);
  console.log(arguments.callee.caller.caller);
  console.log(callTaker.name);
  console.log(callTaker.constructor);
}
 
function callMaker(){
  callTaker("foo","bar",this,document);
}
 
function init(){
  callMaker();
}

For demonstration purposes, you can run the init function above and view the logs in FireBug.

arguments object and its properties

arguments returns ["foo", "bar", Window, Document]

arguments.length returns 4

Note: even though our function has a signature with 5 arguments, length returns only 4 here. This is because the caller sent us only 4 arguments. See below for how we can use Function’s length property to find the number of expected arguments.

arguments.callee returns callTaker(a, b, c, d, e)

Note: callee shows us the signature of the currently executing function and is useful when trying to make recursive calls to a function within its own body.

arguments[1] returns bar

Note: arguments can also be set for functions in an array like format. For example you can set the second argument like this: arguments[1] = 'moo';

Function object and its argument related properties

callTaker.length returns 5

Note: This is the expected number of arguments.

callTaker.caller is the same as arguments.callee.caller and returns callMaker()

Note: we can go up the stack trace and get the caller of the caller etc. For example we can find the function that called callMaker using arguments.callee.caller.caller which returns init().

callTaker.name returns callTaker

callTaker.constructor returns Function()

Note: Since we have not modified the basic behavior, we see the built in function that creates an object’s prototype for our function, which is the Function object.

Basic Usage Sample

var dataArray = ["One", "Two", "Three", "Four"];
 
var lister = function createList(list) {
 if(arguments.length == 3){
  var result = "<" + arguments[1] + ">";
  for (var i = 0; i < arguments[2].length; i++){
   result += "<li>" + arguments[2][i] + "</li>";
  }
  result += "</" + arguments[1] + "l>";
  document.getElementById(arguments[0]).innerHTML = result;
 }
}
 
function makeList(){
 lister("list_HTML","ul",dataArray);
}

Run the sample

References:
JavaScript Stack Trace
Function
arguments

Whats new in Safari 3.1 Web Inspector and Snippet Editor

Safari 3.1 features improvements to the functionality for the Web Inspector developers tool. In now has an improved console for working with JavaScript and DOM, DOM inspector with CSS support, a nice Network analysis tool and search all built in. It is somewhat comparable to the FireBug plugin for FireFox so I will also make some comparisons of their features.
Continue »