{"id":262,"date":"2007-06-16T11:18:53","date_gmt":"2007-06-16T19:18:53","guid":{"rendered":""},"modified":"2016-05-25T23:34:30","modified_gmt":"2016-05-26T06:34:30","slug":"widget-deployment-with-wedje","status":"publish","type":"post","link":"https:\/\/mikeindustries.com\/blog\/archive\/2007\/06\/widget-deployment-with-wedje","title":{"rendered":"How To Keep Widgets From Slowing Down Sites: WEDJE"},"content":{"rendered":"<p>The whole world is going to widgets.  This overused, overhyped term refers to third-party code one places on their website or blog in order to display such things as Flickr photos, Twitter status, or iTunes playlists.  Everybody and their mom is putting out widgets these days, and although only about 1% of them are useful or interesting, they are an important new distribution mechanism that is changing the way companies think about syndication.<\/p>\n<p>But there is a big problem with widgets: <a href=\"http:\/\/www.crunchnotes.com\/?p=408\" target=\"_blank\">they slow down the sites that use them<\/a>.  In the best case, you have a company like Flickr whose servers are almost always snappy, and in the worst case, you have a young startup that is constantly struggling against increasing demand and occasionally can&#8217;t serve up any code at all.<\/p>\n<p>The problem is that in either of these cases, the completion of your site&#8217;s loading and rendering depends on someone else&#8217;s code living on someone else&#8217;s server.  Including a fast and reliable Flickr widget still slows your site down by at least a split second and including a less stable one can leave your site hanging indefinitely.<\/p>\n<p>We&#8217;ve been developing what we think is going to be a gangbusters widget at <a href=\"http:\/\/www.newsvine.com\" target=\"_blank\">Newsvine<\/a> over the last few months but just as we were getting ready to deploy it, <a href=\"http:\/\/www.robgoodlatte.com\" target=\"_blank\">Intern Rob<\/a> and I hacked together what we think is a method of deploying widgets in such a fashion that they don&#8217;t affect the load times of their parent sites whatsoever.<\/p>\n<p>Following is a breakdown:<br \/>\n<!--more--><\/p>\n<h3>Root Causes<\/h3>\n<p>Most widgets are deployed using one of two methods: raw embedding or javascript embedding.<\/p>\n<p>Raw embedding usually involves providing a chunk of <code>object\/embed<\/code> code to display a Flash widget inline.  The advantage of this method is that it works in environments like MySpace which don&#8217;t allow the use of javascript.  The disadvantages are that a) many people don&#8217;t like placing raw Flash code in their pages, b) some widgets aren&#8217;t Flash-based, and c) the widget author can&#8217;t change much after the fact since the widget&#8217;s code is more or less set in stone.<\/p>\n<p>Javascript embedding involves using a <code>script<\/code> include to remotely deploy code into the user&#8217;s site.  The advantage is that it&#8217;s much cleaner and more flexible.  The disadvantage is that it slows sites down a little every time and a <strong>lot<\/strong> when there are problems.<\/p>\n<h3>The Solution: WEDJE<\/h3>\n<p>Providing a raw embed method is still a necessity if your target environment is MySpace, but if you&#8217;re going after people with their own sites\/blogs, javascript embedding is still a better ideal.  We need a catchy acronym for our method in order for people to use it so we&#8217;re going with: WEDJE.  Or, &#8220;Widget Enabled DOM Javascript Embedding&#8221;&#8230; which is an acronym inside of an acronym, so it&#8217;s extra cool.<\/p>\n<p>In a nutshell, here are what the two existing javascript methods do versus what WEDJE does:<\/p>\n<h4>Standard <code>document.write<\/code><\/h4>\n<p>Most javascript embedding simply uses <code>document.write<\/code> to write code into your site inline.  The problem is that if the widget server hangs, the rest of your site can&#8217;t draw until the script is done executing.  This could be a split second or it could be forever.  Many people mistakenly think you can use the <code>defer<\/code> attribute in your script tag to keep this from happening, but <code>defer<\/code> effectively kills the <code>document.write<\/code> function entirely so this is not a solution.<\/p>\n<h4>Deferred <code>innerHTML<\/code> code<\/h4>\n<p>The other method of javascript embedding is to write out a <code>div<\/code> with an <code>ID<\/code>, load the javascript with the <code>defer<\/code> parameter added, and then use <code>innerHTML<\/code> to write to the <code>div<\/code> whenever the script has loaded.  This seems great in theory, but in reality, Internet Explorer is the only browser which seems to properly render the rest of the page before the script is done executing.<\/p>\n<h4>WEDJE<\/h4>\n<p>WEDJE is similar to the <code>innerHTML<\/code> method above except it creates what is effectively a cross-platform, cross-browser defer, enabling your script to load and execute asynchronously across all environments.  We write out a <code>div<\/code> with javascript, then we create a <code>script<\/code> element with javascript, and then we append the <code>script<\/code> element to the <code>div<\/code>, again with javascript.<\/p>\n<p>By linking elements together in this way, browsers appear to completely decouple the loading and execution of our attached javascript from the loading and execution of the original document, which is exactly what we&#8217;re looking for.<\/p>\n<p>An example of WEDJE in action is below.  Reload this page and watch the area below.  There is a 7 second delay in the execution of the javascript file in order to simulate a slow-loading script:<\/p>\n<p><em>This text is before the widget code.<\/em><\/p>\n\r\n<script type=\"text\/javascript\">(function(){document.write('<div id=\"wedje_div_yourcompanyname\"><\/div>');s=document.createElement('script');s.type=\"text\/javascript\";s.src=\"https:\/\/mikeindustries.com\/blog\/scripts\/sleepywidget.php\";setTimeout(\"document.getElementById('wedje_div_yourcompanyname').appendChild(s)\",1);})()<\/script>\r\n\n<p><em>This text is after the widget code.<\/em><\/p>\n<p>Notice how everything loads regardless of the state of the widget?  Voila.<\/p>\n<h3>Caveats<\/h3>\n<p><a href=\"http:\/\/www.robgoodlatte.com\" target=\"_blank\">Intern Rob<\/a> and I are under no illusions that this is rocket science, nor that it hasn&#8217;t already been tried by someone else, nor that it works perfectly.  To the last point, we&#8217;d love your feedback as to what could be improved or where it may not be working.  So far, tested browsers are:<\/p>\n<ul>\n<li>Safari: Mac and PC<\/li>\n<li>Firefox: Mac and PC<\/li>\n<li>Internet Explorer: PC<\/li>\n<li>Opera: Mac and PC<\/li>\n<\/ul>\n<p>1. Here is the sample code which goes in the js file:<\/p>\n\r\n<textarea style=\"width: 450px; height: 100px\">document.getElementById('wedje_div_yourcompanyname').innerHTML+='<img src=\"https:\/\/mikeindustries.com\/blog\/images\/inline\/widgetexample.gif\" width=\"160\" height=\"380\" \/>';<\/textarea>\r\n\n<p>2. Here is the sample code to embed in your page:<\/p>\n<h4>Compact Version (Don&#8217;t use if you serve your pages as application\/xml):<\/h4>\n\r\n<textarea style=\"width: 450px; height: 100px\"><script type=\"text\/javascript\">(function(){document.write('<div id=\"wedje_div_yourcompanyname\"><\/div>');s=document.createElement('script');s.type=\"text\/javascript\";s.src=\"https:\/\/mikeindustries.com\/blog\/scripts\/sleepywidget.php\";setTimeout(\"document.getElementById('wedje_div_yourcompanyname').appendChild(s)\",1);})()<\/script><\/textarea>\r\n\n<h4>Application\/XML Mime-Type Version (thanks <a href=\"http:\/\/www.scottnelle.com\" target=\"_blank\">Scott<\/a>):<\/h4>\n\r\n<textarea style=\"width: 450px; height: 100px\"><script type=\"text\/javascript\" language=\"Javascript\" id=\"wedje_script_yourcompanyname\">(function(){c=document.createElement('div');c.id='wedje_div_yourcompanyname';s=document.getElementById('wedje_script_yourcompanyname');s.parentNode.insertBefore(c,s);w=document.createElement('script');w.type='text\/javascript';w.src='https:\/\/mikeindustries.com\/blog\/scripts\/sleepywidget.php';setTimeout(\"document.getElementById('wedje_div_yourcompanyname').appendChild(w)\",1);})()<\/script><\/textarea>\r\n\n<div class=\"update\"><strong>UPDATE:<\/strong> There is apparently some random IE crashing behavior that can occur using this method upon subsequent page views (but not full reloads). If anyone has any clues, let me know.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The whole world is going to widgets. This overused, overhyped term refers to third-party code one places on their website or blog in order to display such things as Flickr photos, Twitter status, or iTunes playlists. Everybody and their mom is putting out widgets these days, and although only about 1% of them are useful [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[37,282],"tags":[],"class_list":["post-262","post","type-post","status-publish","format-standard","hentry","category-code","category-original"],"_links":{"self":[{"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/posts\/262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/comments?post=262"}],"version-history":[{"count":0,"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/posts\/262\/revisions"}],"wp:attachment":[{"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/media?parent=262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/categories?post=262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mikeindustries.com\/blog\/wp-json\/wp\/v2\/tags?post=262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}