I recently decided to pony up for AddThis Pro. Spread across up to five sites, that’s not very much to pay for a wide variety of well-designed social widgets. Certainly much less than what my time would be worth to reinvent them from scratch.

However, I’m always wary of bogging the site’s performance down with poorly implemented sharing buttons, counters, toolbars, etc. I tried Buffer’s Digg Digg plugin for a little while last year, but it had a noticeable impact on page jankiness and load times even with the deferred initialization option enabled.

With performance in mind, I was happy to discover that AddThis supports loading the bulk of its client-side code asynchronously. However, I was less happy to find that it didn’t seem to work when I followed the instructions on their site, resulting in a JavaScript error and no AddThis widgets at all.

In this post, I’ll cover why you should consider using asynchronous scripts, how to fix the addthis_config not defined error, and an alternate way of asynchronously including the AddThis scripts that I think may be a better approach than the one AddThis recommends.

Why should you use asynchronous scripts in the first place?

When you reference nonessential JavaScript from third parties, it’s good to use some sort of asynchronous loading approach if possible. The situation has improved somewhat in recent years, but an errant, blocking JavaScript include can still have a surprisingly large impact on how a page appears to perform if it’s in the wrong place or takes too long to load.

Even if you include third-party scripts at the very bottom of your pages to stave off total disaster, blocking scripts still delay the DOMContentLoaded event and any initialization code that waits until then to execute. Worse, an unresponsive third-party server might postpone that DOM ready event for dozens of seconds — an eternity when it comes to web performance.

Loading scripts asynchronously goes a long way toward mitigating that issue. By injecting scripts in ways that allow browsers to begin loading them and then immediately continue parsing and rendering the rest of the page, these render-blocking delays and pauses can be totally eliminated in most cases.

The main drawback is that asynchronously loaded scripts will take effect a bit later than they would otherwise have if synchronously included at the same location. It’s also difficult to ensure a specific order of execution, which can be tricky sometimes.

However, those are both small prices to pay when loading ancillary features like sharing buttons.

How AddThis recommends using their scripts asynchronously

The AddThis support page about taking advantage of its asynchronous loading mode was straight to the point. It suggested replacing this synchronous code:

With this version instead:

Unfortunately, making that change on my site resulted in a JavaScript error and left me with no AddThis widgets at all.

Fixing the addthis_config not defined error

The problem is straightforward enough if you’re familiar with JavaScript, but probably not at all if you’re not a developer.

What’s going on is that even though the AddThis script is loading asynchronously, the two lines in the script block afterward run immediately, before the main AddThis script has had a chance to load and run. Among other things, that means addthis_config doesn’t exist yet.

For that reason, it doesn’t make sense to the browser when we try to assigning a value to addthis_config.pubid right away. It’s something like asking someone to deliver an important letter to a particular apartment number, having accidentally given them the street address of an empty parcel of land.

The problem is easy enough to fix. You can change the script to initialize addthis_config as a new object before attempting to set its pubid:

The new line preceding the old code just tells the browser to assign a new, empty object to addthis_config if nothing has been assigned to it yet. Now, we can safely set our pubid on the empty object.

Later, when AddThis’ full payload runs, it will fill addthis_config out with a variety of other properties. It does preserve any settings added beforehand though, including our pubid.

That’s not async. THIS is async.

After working around that JavaScript error, the #async=1 option does push the bulk of AddThis’ JavaScript payload out of the synchronous rendering path. It doesn’t fulfill the true potential of asynchronous script loading though because the bootstrapping script is still loaded synchronously.

If AddThis’ servers are down or responding very slowly, the small bootstrapping script that still loads synchronously can bring your site to its knees just as effectively as if you loaded the entire payload synchronously.

Luckily, the full script works just fine if you load it using this common async script loading approach:

Now the entire script loads asynchronously in one shot. No errors and no blocking.

Note: Asynchronous isn’t always best

You might have noticed that I italicized “nonessential” when describing why you should load these scripts asynchronously. That’s because there’s an interesting quirk which makes decisions about script includes a bit more complicated.

As browser vendors have innovated over the years, a feature that some have added is the ability to scan ahead of blocking, synchronous scripts in search of assets to preload while the blocking script is parsed and executed. Though browsers still can’t execute synchronous scripts in parallel or out of order, they can get the next script loaded and ready to run as quickly as possible when its turn comes. Clever.

If you use the script element injection approach shown above, browsers will not suss out that they should preload those scripts in advance. At least for now, they’re limited to searching ahead for the src and href attributes of traditional HTML elements.

In other words, if you load every script on a page using dynamic script injection, it will actually take longer to load and execute all of those scripts in most modern browsers.

For superfluous features like sharing widgets, that’s an acceptable tradeoff. However, be careful about applying that approach too broadly. When you’re loading scripts crucial to a page’s fundamental purpose — especially scripts loaded from the same server as the page’s content — async by way of dynamic script injection probably isn’t worth the complexity or potential loss of preloading.