Scott Hanselman

Easy accelerated 3D Games in a browser with JavaScript and WebGL using Three.js or Babylon.js

June 11, '14 Comments [12] Posted in Gaming | Javascript | Open Source
Sponsored By

Let's ignore that we haven't got a web-agreed-upon way to do just about anything, much less basic line-of-business apps with data-bound text boxes over data, and just revel in the fact that we can do hardware-accelerated 3D graphics in our browsers with WebGL. This works today in all the latest browsers.

I noticed this fantastic mini-game promoting Assassin's Creed over at http://race.assassinscreedpirates.com that uses WebGL via a library called Babylon.js. On my Windows machine it runs perfectly in IE11, Chrome 37, or Firefox 30. (Yes, in retrospec, the version numbering for browsers is getting out of hand.)

Some folks on Macs have reported issues with WebGL. Check out https://www.browserleaks.com/webgl for YOUR browser's capabilities.

This Pirate Ship game is really worth checking out and it's fun for the kids. You can also check out the Developer Teardown and learn how they built it.

3D Assassin's Creed Pirates in my browser

I wanted to get a better understanding of exactly how difficult it is (or easy!) to get in to WebGL in the browser. I found this article over at SitePoint by Joe Hewitson and started with some of his sample code where he compares two popular WebGL libraryes, three.js and babylon.js. The Assassin's Creed game here is written using Babylon.js.

Three.js seem to be  a general layer on top of WebJS, aiming to make scene creation and animation easy. Using Joe's sample (that I changed a little) along with a texture.gif, I was able to make this spinning 3D cube easily.

There's a live example running at http://hanselstorage.blob.core.windows.net/blog/WebGL.html you can see in your modern browser. Below is just a static image.

I would have animated it but that would have been a meg. ;)

Three.js is on the left and Babylon.js is on the right. It doesn't really matter given the static image, but one think you'll notice immediately if you run the live sample is that you can zoom in and out, pan, grab, and manipulate the babylon.js cube. I could have hooked up some events to the three.js cube, or perhaps added a physics engine like Physijs and made it interact with the world, I suppose. It struck me though, that this little example shows the difference in philosophy between the two. Babylon seems to be more of a game engine or a library that wants to help you make games so there's interactions, collision detection, and lighting included.

Three.js supports many renderers, cameras, and lighting. You can use all WebGL capabilities such as lens flares. It supports all the usual objects and geometries as well. Their examples are extensive with over 150 coding examples covering everything you'd want to know from fonts, models, textures, to sounds. There's even an in-browser Three.js editor.

Babylon includes a lot including a physics engine from cannon.js built in, full scene graph, offline mode, textures, special effects and post processes, many cameras including Oculus Rift (!) lots of meshes. Babylon.js even supports standard Gamepads via like the Xbox One controller natively via the Gamepad API spec.

Anyway, here is the cube on the right from Joe's code that I modified slightly, using babylon.js:

// Babylon.js 
var canvas = document.getElementById('babylonCanvas');
var engine = new BABYLON.Engine(canvas, true);
var sceneB = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("camera", 1, 0.8, 10, new BABYLON.Vector3(0, 0, 0), sceneB);

var light = new BABYLON.DirectionalLight("light", new BABYLON.Vector3(0, -1, 0), sceneB);
//light.diffuse = new BABYLON.Color3(1, 0, 0);
//light.specular = new BABYLON.Color3(1, 1, 1);

var box = BABYLON.Mesh.CreateBox("box", 3.0, sceneB);
var material = new BABYLON.StandardMaterial("texture", sceneB);
box.material = material;
material.diffuseTexture = new BABYLON.Texture("texture.gif", sceneB);

sceneB.activeCamera.attachControl(canvas);

engine.runRenderLoop(function () {
box.rotation.x += 0.005;
box.rotation.y += 0.01;
sceneB.render();
});

I also commented out the lighting but you can see how easy it is to add lighting to a scene if you like. In this case there was a diffuse red light along with a specular white.

With babylon.js I could change the size of the scene by changing the size of the canvas. With three.js the width and height are pulled in programmatically from the enclosing div.


Here is the near-same box created with three.js.

// Three.js 
var div = document.getElementById('three');
var height = div.offsetHeight;
var width = div.offsetWidth;

var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
div.appendChild(renderer.domElement);

var camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
camera.position.z = 400;

var sceneT = new THREE.Scene();

var cube = new THREE.CubeGeometry(200, 200, 200);

var texture = THREE.ImageUtils.loadTexture('texture.gif');
texture.anisotropy = renderer.getMaxAnisotropy();

var material = new THREE.MeshBasicMaterial({ map: texture });

var mesh = new THREE.Mesh(cube, material);
sceneT.add(mesh);

animate();

function animate() {
requestAnimationFrame(animate);

mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render(sceneT, camera);
}

Both libraries have amazing Examples Galleries and you should check them out.

Also note that there's a contest running until June 20th, 2014 over at http://www.modern.ie/en-us/demos/assassinscreedpirates where you'll create your own shader within the browser and submit it for judging. Contestants must be over 16 years of age and from one of the following countries: United States of America, United Kingdom, France, Germany, Spain, or Australia. The contest starts here and the grand prize is an Assassin’s Creed Collector’s Black Chest Edition and an Xbox One.

Create your Shaders in the browser

Even if you don't win, do check out the in-browser shader editor. It's amazing.


Sponsor: A big welcome to my friends at Octopus Deploy. They are sponsoring the blog feed this week. Using NuGet and powerful conventions, Octopus Deploy makes it easy to automate releases of ASP.NET applications and Windows Services. Say goodbye to remote desktop and start automating today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Recent JavaScript Jabber Podcast - Microsoft, not Microsoft, and the Web

August 20, '13 Comments [41] Posted in Javascript | Podcast
Sponsored By

loraxI was a guest recently on a podcast called JavaScript Jabber. I enjoy checking out other folks' podcasts and how they run things. I actually talked to the guys about sound quality for about 30 min before the actual recording started.

Their show is about JavaScript exclusively so we spent about an hour talking shop.

Here's a few quotes...yes, I'm quoting myself. On my blog.  We talked about Open Source:

I don’t care if it’s not Entity Framework. If you want to use NHibernate or RavenDB or CouchDB, dude, knock yourself out. But ultimately, the dirty little secret about Microsoft is they want you to run on Windows. Okay, well you don’t run Windows. You guys run Macs. Okay. But maybe you’ll discover that Azure is actually a pretty kickass cloud service and you’ll run your stuff on Azure, which is Windows.

We talked about using the client machine more effectively:

I hear a lot of people say, "Hey, we run a web farm and we’ve got about ten machines in the farm and it just can’t handle the load. We’re going to need to buy an 11th machine." Then you talk to them and they’ll say something like, "Well we’ve got 10,000 people hitting the site," and I’ll think to myself, "Okay, you’ve got 10 machines in the farm and you have 10,000 people hitting the sites. All those people have quad processors, even if they have a phone. Are those processors really working hard? You’ve got 40,000 unused processors just sitting there and they’re waiting for your 10 processors to give them angle brackets. What if you gave them curly braces and let them do the work?”

I think the podcast turned out fairly well, although there was a little tension as I felt I was being asked to make declarative statements and defend historical stuff I didn't work on. I think I made it very clear that my opinions about the industry are just that, opinions, and mine alone. That said, we talked about node, JavaScript in general, the way the industry is moving with respect to where work happens (client vs. server) and a bunch of other things.

They called this episode "JavaScript Strategies at Microsoft with Scott Hanselman." Other than the "with Scott Hanselman" part, this title is problematic.

The hosts are fine folks and I had a pleasant time. I think because of the title of the episode this particular episode has been getting a LOT of Tweets and appeared on Hacker News and Reddit for a short while. I wouldn't have chosen this title, myself.

  • It implies I have anything to do with JavaScript at Microsoft.
    • I don't. I do work in Azure and Web Tools and I often give my opinions on the JavaScript Editor, on what we do with Node, and how frameworks like Ember and Angular will be presented in VS, but I am not in charge of anything. I give feedback just like dozens (hundreds?) of other random folks inside the Big House.
  • It implies I'm some how strategic, strategically involved or know strategery within JavaScript at Microsoft.
    • Again, JavaScript on the client is the Chakra engine and the IE team. I don't work for them, no do I claim (and never have) to speak for them.
  • It implies I'm a spokesman for Microsoft.
    • I'm an enthusiast and a teacher, but not a marketer or spokesman. I speak, and yes, I do have this blog, but it's mine and its writings and opinions are mine. I often write about Microsoft stuff because I work there, but I worked elsewhere for 15 years and blogged that also. I blogged and podcast before I got to Microsoft and I will continue to blog and podcast after I leave. I am not my job.

I would encourage you to check out the podcast episode yourself and see what you think. It also includes a complete transcription, which is a nice touch and very important.


Sponsor: A big thanks, and a welcome to Aspose for sponsoring the feed this week! Check out their Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

A rich new JavaScript code editor spreading to several Microsoft web sites

August 1, '13 Comments [33] Posted in Javascript
Sponsored By
Where is this JavaScript-based editable code area coming from?

I noticed yesterday that some C#, JavaScript and CSS files I had sitting in SkyDrive were suddenly editable.

Editable code in SkyDrive

Not just editable, but there's also autocompletion of strings (not quite intellisense, as it's just one file at a time) and token/symbol recognition.

Editable code in SkyDrive

Plus, this editor looked REALLY familiar to me. I started looking.

I looked over at the Windows Azure Portal, where developers can write node.js to make web services directly in the browser. Here we've got dropbox autocomplete, tooltips with syntax errors and even some basic symbolic refactoring!

Azure Mobile Service's rich code editor

Below you can see the editor in Azure Mobile Services throwing a tooltip syntax error. Is this happening on the server?

Untitled2

Then I remember TypeScript's "playground" online that shows how TypeScript turns into JavaScript. This is split-screen with TypeScript on the left and JavaScript on the right.

The TypeScript Playground

Then I went to look at TFS Online's stuff at http://tfs.visualstudio.com/ where I made an account http://hanselman.visualstudio.com to host private Git repos for side projects.

Inline comments in TFS online

Notice that in TFS Online this editor is used for diffs and comparisons, but also includes inline threaded comments! This is all in JavaScript, people.

The editor in a side by side diff

I brought up F12 tools just to check.

The javaScript editor open in SkyDrive

That's pretty unambiguous. Looking at the CSS by just clicking on editor.main.css. The "vs" in the div's class point to a vs-theme.css that I presume is to set the colors and make the text editor look familiar.

editor.main.css

Looking in editor.main.js, it's all minified, but it's cool to see.

editor.main.js

This JavaScript code editor/viewer component is on a TFS site, an Azure site and a SkyDrive site, being used very different divisions across Microsoft. Very cool to see code reuse, but also a good experience replicated. Kudos to the SkyDrive team for recognizing a good thing and putting it into production. It'll be interesting to see where else this editor pops up in the future.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

JavaScript is Web Assembly Language and that's OK.

May 24, '13 Comments [48] Posted in Javascript
Sponsored By

Some years ago I said that JavaScript is the Assembly Language of the Web. In fact, lots of people said it, because it's true. Later, some folks disagreed, saying that this is an inaccurate analogy. Of course, it is inaccurate because it's an analogy. That said, as analogies go, it's pretty good. Sure, assemblers are architecture and processor specific. Maybe "JavaScript is the Web's Bytecode" is better. At the very least, JavaScript is a totally reasonable compile target.

Given that (using Wikipedia as a dictionary here and has a decent definition:

An assembly language is a low-level programming language for a computer, or other programmable device, in which there is a very strong correspondence between the language and the architecture's machine code instructions.

It's initially not clear that JavaScript is a good assembly language as it's a high-level programming language that is itself interpreted, then JIT-ted, then turned into machine instructions. Phrased differently, JavaScript floats pretty high in the stack. Certainly every processor has its own assembler and they are very specific, but the browser's JavaScript VM is what runs the "new machine code." There's only one processor architecture. The Web. (again, analogy!)

JavaScript remains a popular transpilation/compilation target. From Google's GWT to Clojure to TypeScript to CoffeeScript, it all stops at JavaScript because JavaScript is the ubiquitous virtual machine that we already have installed on our machines.

Google Native Client (NaCl) is great and will likely have a role to play, but there's only one language that works everywhere without installation or trouble and that's JavaScript.

asm.js compilation & execution pipelineWe don't all have x86 machines. We don't have have machines that we could feed assembler or C. Certainly not in a portable way. JavaScript is the great portable equalizer.

There's languages that transform to JavaScript like TypeScript and CoffeeScript and HAXE and so many more, but many of these are arguably transformations, not compilations. They also tend to compile to lots of different kinds of JavaScript.

Enter asm.js. Why not take the sprawling language that is JavaScript and pick just the subset that one would want if one were to compile something to it? Why not take the assembly-esque parts of JavaScript and formalize it? Mozilla is doing this with the clear goal to compile things to JavaScript and make it perform well. Their FAQ says they're seeing slowdowns around a factor of two, which is amazing, in case you're wondering. It's also worth noting that I, as a user, don't care if you compile your C to JavaScript. I just want a great experience on the open web, and that's another reason that targeting JavaScript moves the web forward.

Working in tandem, there's emscripten, a LLVM bitcode to JavaScript compiler. We can take C/C++ and compile it to JavaScript. Don't buy it? They ported Unreal Engine 3 in 4 days with asm.js as the target.

You can argue that JavaScript isn't the x86 or Assembly of the web. You can argue all you want. It's still happening.

As our great philosopher Kosh from Babylon 5 once said: "The avalanche has already started. It is too late for the pebbles to vote."

The avalanche has already started. It is too late for the pebbles to vote.

It's not clear that JavaScript is the end state. In fact, if anything it's clear there is no end state. But along the way we will - actually are - passing though the JavaScript as Assembler part of the trip.


Sponsor: Big thanks to SoftFluent for sponsoring the feed this week! Less Plumbing, More Productivity! Generate rock-solid foundations for your .NET applications from Visual Studio and focus on what matters!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

CDNs fail, but your scripts don't have to - fallback from CDN to local jQuery

April 30, '13 Comments [46] Posted in ASP.NET | Javascript
Sponsored By

CDN issues in the Northeast

There's a great website called http://whoownsmyavailability.com that serves as a reminder to me (and all of us) that external dependencies are, in fact, external. As such, they are calculated risks with tradeoffs. CDNs are great, but for those minutes or hours that they go down a year, they can be super annoying.

I saw a tweet today declaring that the ASP.NET Content Delivery Network was down. I don't work for the CDN team but I care about this stuff (too much, according to my last performance review) so I turned twitter to figure this out and help diagnose it. The CDN didn't look down from my vantage point.

I searched for things like "ajax cdn,"microsoft cdn," and "asp.net cdn down" and looked at the locations reported by the Twitter users in their profiles. They had locations like CT, VT, DE, NY, ME. These are all abbreviations for states in the northeast of the US. There were also a few tweets from Toronto and Montreal. Then, there was one random tweet from a guy in Los Angeles on the other side of the country. LA doesn't match the pattern that was developing.

I tweeted LA guy and asked him if he was really in LA or rather on the east coast.

Bingo. He was VPN'ed into Massachusetts (MA). I had a few folks send me tracerts and sent them off to the CDN team who fixed the issue in a few minutes. There was apparently a bad machine in Boston/NYC area that had a configuration change specific to the a certain Ajax path that had gone undetected by their dashboard (this has been fixed and only affected the Ajax part of the CDN in this local area).

More importantly, how can we as application developers fallback gracefully when an external dependency like a CDN goes down? Just last week I moved all of my Hanselminutes Podcast images over to a CDN. If there was a major issue I could fall back to local images with a code change. However, if this was a mission critical site, I should not only have a simple configuration switch to fallback to local resources, but I should also test and simulate a CDN going down so I'm prepared when it inevitably happens.

With JavaScript we can detect when our CDN-hosted JavaScript resources like jQuery or jQuery UI aren't loaded successfully and try again to load them from local locations.

Falling back from CDN to local copies of jQuery and JavaScript

The basic idea for CDN fallback is to check for a type or variable that should be present after a script load, and if it's not there, try getting that script locally. Note the important escape characters within the document.write. Here's jQuery:

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
<script>
if (typeof jQuery == 'undefined') {
document.write(unescape("%3Cscript src='/js/jquery-2.0.0.min.js' type='text/javascript'%3E%3C/script%3E"));
}
</script>

Or, slightly differently. This example uses protocol-less URLS, checks a different way and escapes the document.write differently.

<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-2.0.0.min.js">\x3C/script>')</script>

If you are loading other plugins you'll want to check for other things like the presence of specific functions added by your 3rd party library, as in "if (type of $.foo)" for jQuery plugins.

Some folks use a JavaScript loader like yepnope. In this example you check for jQuery as the complete (loading) event fires:

yepnope([{
load: 'http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js',
complete: function () {
if (!window.jQuery) {
yepnope('js/jquery-2.0.0.min.js');
}
}
}]);

Even better, RequireJS has a really cool shorthand for fallback URLs which makes me smile:

requirejs.config({
enforceDefine: true,
paths: {
jquery: [
'//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min',
//If the CDN location fails, load from this location
'js/jquery-2.0.0.min'
]
}
});

//Later
require(['jquery'], function ($) {
});

With RequireJS you can then setup dependencies between modules as well and it will take care of the details. Also check out this video on Using Require.JS in an ASP.NET MVC application with Jonathan Creamer.

Updated ASP.NET Web Forms 4.5 falls back from CDN automatically

For ASP.NET Web Forms developers, I'll bet you didn't know this little gem. Here's another good reason to move your ASP.NET sites to ASP.NET 4.5 - using a CDN and falling back to local files is built into the framework.

(We've got this for ASP.NET MVC also, keep reading!)

Fire up Visual Studio 2012 and make a new ASP.NET 4.5 Web Forms application.

When using a ScriptManager control in Web Forms, you can set EnableCdn="true" and ASP.NET will automatically change the <script> tags from using local scripts to using CDN-served scripts with local fallback checks included. Therefore, this ASP.NET WebForms ScriptManager:

<asp:ScriptManager runat="server" EnableCdn="true">
<Scripts>
<asp:ScriptReference Name="jquery" />
<asp:ScriptReference Name="jquery.ui.combined" />
</Scripts>
</asp:ScriptManager>

...will output script tags that automatically use the CDN and automatically includes local fallback.

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
(window.jQuery)||document.write('<script type="text/javascript" src="Scripts/jquery-1.8.2.js"><\/script>');//]]>
</script>

<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.24/jquery-ui.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
(!!window.jQuery.ui && !!window.jQuery.ui.version)||document.write('<script type="text/javascript" src="Scripts/jquery-ui-1.8.24.js"><\/script>');//]]>
</script>

What? You want to use your own CDN? or Googles? Sure, just make a ScriptResourceMapping and put in whatever you want. You can make new ones, replace old ones, put in your success expression (what you check to make sure it worked), as well as your debug path and minified path.

var mapping = ScriptManager.ScriptResourceMapping;
// Map jquery definition to the Google CDN
mapping.AddDefinition("jquery", new ScriptResourceDefinition
{
Path = "~/Scripts/jquery-2.0.0.min.js",
DebugPath = "~/Scripts/jquery-2.0.0.js",
CdnPath = "http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js",
CdnDebugPath = "https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.js",
CdnSupportsSecureConnection = true,
LoadSuccessExpression = "window.jQuery"
});

// Map jquery ui definition to the Google CDN
mapping.AddDefinition("jquery.ui.combined", new ScriptResourceDefinition
{
Path = "~/Scripts/jquery-ui-1.10.2.min.js",
DebugPath = "~/Scripts/jquery-ui-1.10.2.js",
CdnPath = "http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js",
CdnDebugPath = "http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.js",
CdnSupportsSecureConnection = true,
LoadSuccessExpression = "window.jQuery && window.jQuery.ui && window.jQuery.ui.version === '1.10.2'"
});

I just do this mapping once, and now any ScriptManager control application-wide gets the update and outputs the correct fallback.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
(window.jQuery)||document.write('<script type="text/javascript" src="Scripts/jquery-2.0.0.js"><\/script>');//]]>
</script>

<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
(window.jQuery && window.jQuery.ui && window.jQuery.ui.version === '1.10.2')||document.write('<script type="text/javascript" src="Scripts/jquery-ui-1.10.2.js"><\/script>');//]]>
</script>

If you want to use jQuery 2.0.0 or a newer version than what came with ASP.NET 4.5, you'll want to update your NuGet packages for ScriptManager. These include the config info about the CDN locations. To update (or check your current version against the current) within Visual Studio go to Tools | Library Package Manager | Manage Libraries for Solution, and click on Updates on the left there.

image

Updated ASP.NET Web Optimization Framework includes CDN Fallback

If you're using ASP.NET MVC, you can update the included Microsoft.AspNet.Web.Optimization package to the -prerelease (as of these writing) to get CDN fallback as well.

Get Optimization Updates by "including PreRelease"

Note that I've on the Updates tab within the Manage NuGet Packages dialog but I've selected "Include Prerelease."

Now in my BundleConfig I can setup my bundles to include not only the CdnPath but also a CdnFallbackExpression:

public static void RegisterBundles(BundleCollection bundles)
{
bundles.UseCdn = true;
BundleTable.EnableOptimizations = true; //force optimization while debugging

var jquery = new ScriptBundle("~/bundles/jquery", "//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js").Include(
"~/Scripts/jquery-{version}.js");
jquery.CdnFallbackExpression = "window.jQuery";
bundles.Add(jquery);
//...
}

Regardless of how you do it, remember when you setup Pingdom or other availability alerts that you should be testing your Content Delivery Network as well, from multiple locations. In this case, the CDN failure was extremely localized and relatively short but it could have been worse. A fallback technique like this would have allowed sites (like mine) to easily weather the storm.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Page 1 of 21 in the Javascript category Next Page

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.