3PO#fail

June 16th, 2012. Tagged: browsers, JavaScript, performance

So I was flipping through recent slides from Steve Souders and came across a reference to a nice post from Pat Meenan explaining how he setup blackhole.webpagetest.org and how you can edit your hosts file to send third party scripts to the black hole simulating a firewall-blocked or down third party and the effect on your site. (whew, long sentence)

I thought to would be nice to make that easier and have people see (and demonstrate to bosses and clients) how damaging frontend SPOF (Single Point Of Failure) can be. A browser extension maybe. A Chrome extension, because I've never made one. The idea marinated undisturbed for a few days and last night all of a sudden I got to work.

May I present you...

Now available at the Chrome web store.

3PO?

3PO = 3rd Party Optimization

I find it amusing, hope you do too

#fail?

Well, yeah. What happens to your site when a 3rd party goes down? Does it still work?

Is it true that your site is only down when it's down? Or it's down when:

It's down
or
Facbeook is down
or
Google is down
or
Twitter is blocked in your office
or
code.jquery.com is down
...and so on and so on.

This extension helps you check what happens with a click of button.

What 3PO#fail does

Very simple: it's looking for scripts from a list of suspects (api.google.com, platform.twitter.com, etc) and redirects them to blackhole.webpagetest.com

The current list of 3rd parties:

var urls = [
  '*://ajax.googleapis.com/*',
  '*://apis.google.com/*',
  '*://*.google-analytics.com/*',
  '*://connect.facebook.net/*',
  '*://platform.twitter.com/*',
  '*://code.jquery.com/*',
  '*://platform.linkedin.com/*',
  '*://*.disqus.com/*'
];

How?

Install the extension. Load your page. Or mashable.com for example. Then this happens:

It's a button with # on it. Click it. It turns red.

The extension now listens to script requests made to one of the suspect domains.

Now shift-reload the page. If a 3rd party script is found, it's redirected to the black hole and then a counter appears.

Observe whether or not the page is usable when a third party is down. Enjoy and demo to your boss. Tell them: sites do go down, companies ban social networking sites, and btw what do you think will happen when you visit China and load our site?

If you're looking for a page to try, go to mashable or business insider or, ironically, test the extension's page in Chrome web store. Turns out they include Google+'s button synchronously.

Dupe

Here come the LOLz. I blasted this extension out to Steve Souders and back he came with: doh, Pat Meenan also did a Chrome extension to do just this.

Bwahaha. What? You snooze, you miss a whole new tool by Pat Meenan himself.

Here's Pat's extension: SPOF-O-Matic. Try it, use it. It looks more thought out than mine definitely. And there's more code. Maybe Pat spend more time than a night on it. Or maybe he didn't, he's an amazing hacker and half! I mean, uh, webpagetest, hello!

I'll definitely "borrow" his list of 3rd parties which has more entries than mine.

Oh well, you live, you learn (to write Chrome extensions)

Chrome extensions

Creating a Chrome extension was a first for me and was mostly frictionless. Well documented, plenty of samples (try to browse the samples in the repository, because downloading ZIP files is too many clicks). Debugging the extension in the same web inspector is a big plus! Overall I think it's easier to write a Chrome extension than a FF one. Although the last I checked, FF has improved a lot.

Now for the nitpicks.

The API is sometimes irritating. I mean things like

setTitle({title: "My title"});

or

setBadgeText({text: "My text"});

Doplicating title, title, title is annoying. Sometimes it's title, sometimes text, or path or name. Method name appears short but in fact you have to remember one more thing - a property name in a config object. Sounds more like setTitleWithTitle(title) which is just as ridiculous (and popular in Obj-C it seems). Anyway.

The web store asks you for 5 bucks to register and submit an extension. Credit card and all. I didn't like that.

My extension was held for a review which doesn't always happen. The help section says 2-3 business days, but it turned out to be only hours for me. Got a nice email saying the extension is approved and also an explanation why it was held for review. Nice touch.

Code

The code is here: https://github.com/stoyan/3PO-fail. There's not a lot of it. A manifest file and an script that listens to specific URLs and request types in a onBeforeRequest event.

Stripping away UI stuff here's all there is to it.

Callback function which redirects the request:

function failer(info) {
  console.log(info.url); // test
  return {
    redirectUrl: 'https://blackhole.webpagetest.org'
  };
}

There's no logic here because the API allows you to let the browser do request inspection and filtering for you. Here all you do is return an object with a redirectUrl property.

And how do you setup your callback to be invoked?

chrome.webRequest.onBeforeRequest.addListener(
  failer,
  {
    urls: urls,
    types: ['script']
  },
  ["blocking"]
);

You specify your callback to be invoked only for script requests and only those that match a URL in the url array (see above)

The end to the SPOF

All you have to do is load third party scripts synchronously. See here the BFF function for an example. Yet, so many sites are not doing it. There's a need for people to understand this problem. Let's call it demand for advocacy. And now there's supply of 2 brand new tools that make it in-you-face obvious what the damaging effects are.

Random

I went over some of the pages that Steve has listed in his calendar blog post: Business Insider and O'Reilly. O'Reilly is better now and it uses my BFF script (nice, 'scuse me there's something in my eye). Business Insider is almost there. The social stuff is async now, but code.jquery.com is still a SPOF. Funny enough they have a blocking script tag pointing to twitter, but it has a class "post-load". So a script kicks in before this tag and replaces it with async loading. I wonder: why the trouble and not just go async to begin with?

Tell your friends about this post on Facebook and Twitter

Sorry, comments disabled and hidden due to excessive spam.

Meanwhile, hit me up on twitter @stoyanstefanov