Site improvements - fighting with Disqus

From Trephine

Revision as of 05:37, 12 May 2009 by Jimbojw (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search
« JavaScript task chaining Adventures in Rhino - setters and getters »

[subscribe] Recent blog entries

Live Demos

Site improvements - fighting with Disqus

A few weeks ago I spent some time speeding up trephine.org by reducing the number of dependencies and implementing CSS sprites. That effort included rearranging the way that the DISQUS comment system is incorporated into blog articles. Today I had to redo about half that work due to changes in DISQUS.

First off, let me say that I love DISQUS. I am a firm believer in the software-as-a-service concept, and their embeddable threaded comment system, on the whole, is pretty solid. Disqus comments are used throughout this site, and even though the site is powered by MediaWiki and I have written a fairly popular comment extension called ArticleComments, I have no plans to switch to another system in the foreseeable future.

Having said all that, there are a few critical design mistakes in Disqus' implementation which have become a major pain to me. It's possible that there are simple workarounds or that I'm just doing it wrong. If that's the case, please leave me a comment so that I can get on the right path.

When you create an account with Disqus and go through the embedding steps, you are given a scriptlet which is to be embedded on any page that is supposed to have disqus comments. For example, the script for trephine.org is available at:

http://disqus.com/forums/trephine/embed.js 

This brings us to Disqus' first regrettable design decision, using document.write() to embed the necessary CSS styles into the host page:

if (!window.disqus_no_style) {
	document.write('<style type="text/css" media="screen">\
	 #dsq-content #dsq-comments .dsq-comment {\
	 list-style-type: none;\
	 ...SNIP...
	 margin: 5px 0 0 0px;\
	 }\
	 </style>\
	');
}

As you can see, as long as the variable window.disqus_no_style isn't set to true (or something that evaluates to true in a boolean context), the above code will inject a new <style> tag into the DOM by means of document.write().

Clearly the Disqus team expects that you will directly include this script into your page via a <script> tag. Consider what would happen if the embed.js file was to be incorporated into the DOM after the window's onload event has fired (say by creating a new element and using appendChild() to slap it onto the body). What do you think would happen?

Provided that disqus_no_style hasn't been set, this would cause the document.write call to overwrite the existing document, in effect taking the user to a new blank page which contains just a single style tag. Not good.

You might be asking why someone would want to dynamically load the script tag anyway. The reason is performance. When a web browser encounters a script tag, it must immediately execute the script pointed to before continuing to render the page. Sometimes loading embed.js would take longer than expected, forcing the rest of the site to hang, waiting for Disqus to finish before doing anything else.

This lag happened frequently enough that I felt it necessary to remove Disqus from the critical path and include it dynamically on window load. Since comments generally appear towards the bottom of the screen, a given user is unlikely to ever even notice the delay.

However, as you recall, loading embed.js dynamically suffers from the document.write problem unless you set the disqus_no_style variable. So naturally I set that variable, killing the inline style tag, and all the Disqus CSS with it.

Due to the highly stylized nature of Disqus, running it completely without CSS is not an option. So now the problem is determining the proper CSS to include and saving it to a separate external CSS file. This is the step which I had to redo on the heels of Twitter comments & Mini-Profiles, since my old CSS couldn't account for Mini-Profiles.

So what should Disqus do differently? First and formost, the embed script shouldn't use document.write()! It destroys a script's flexibility.

Secondly, they should remove all the static CSS content from the dynamically generated embed.js files. Instead of injecting a style tag into the DOM with document.write, they should dynamically create a <link> element, set all necessary properties, then append it to the document's HEAD.

In addition to solving the dynamic loading problem outlined before, this should also result in better performance from Disqus' standpoint. That is, if all the CSS were consolidated into a single, static, minimized, content delivery network'd CSS file, it would probably significantly decrease the total bandwidth necessary to service all those myriad Disqus comment systems installed around the world.

Finally, by publishing a canonical static CSS file, authors could add the <link> tags and set disqus_no_style themselves to avoid waiting for the CSS to load later. Or, authors could easily concatenate the disqus static file with their own to cut down on the total number of requests necessary to load the page.

Anyway, that about wraps up my Disqus rant. Again, it's a great system overall, and I generally recommend it. If it wasn't for the problems described here, I'd have no reservations whatsoever.

Good luck, I hope this helps!

--Jim R. Wilson (jimbojw) 04:33, 6 May 2009 (UTC)
Personal tools