Saturday, July 25, 2015

My experiment with golang and social counters

Starting with my frustration while building the scroll website: the social buttons are freaking slow to load. Especially on pages that has a lot of scripts (like mine) it is way worse. The buttons usually take minutes to show up and when they do, each of them render differently from the rest. Thanks Facebook, Twitter and Google for that.

So I went in and found a few options. It looks like people made a few scripts that will collect the counters via AJAX (on user browser) and render the buttons with images. Some use data URI to avoid triggering more requests, brilliant! Since I wanted to make something super simple and fast to use, I decided to have one script that does all of those. The server will keep track of the counters and put them in the script so everything needed is one and only one request.

I needed 3 social networks and each of them has different ways to retrieve the counters so I figured the server has to make the requests asynchronously, cache the values for sometime and return the bundled js. My goal is to have it at maximum 50KB and delivered within 500ms. According to my measurement, current scripts from the social networks are way more than that:

  • Facebook sdk.js is the worst contender at about 164KB 
  • Twitter's widgets.js is 107KB
  • Google is the winner here, their platform.js is only 37KB
At first I wanted to do this with Node.js because it's fairly simple and it looks like all output is javascript anyway. Turned out making 3 async http requests and merging the results together is quite complicated (callback hell, anyone?). So I switched to use golang since I tried their channel before and it seems to be a good fit. The project went well and I have them running at both Google App Engine and Heroku at the moment:
The code is pushed to GitHub too, with a simple demo site which makes use of the Heroku instance: http://hoangson.vn/go-socialcounters/. The all.js script is only 14KB (8KB gzip) and normally finished loading in less than a second. I also added a jQuery Plugin script for advanced usage (it fetches a heavily cached jsonp file). The project uses data URI as the other scripts that I found but those images do not look good in high resolution screens so I try to detect SVG support and use SVG whenever possible.

I hope this project is useful for someone.