This post is over 6 months old. Some details, especially technical, may have changed.

Modernizr & RequireJS

I've been pulling a lot of JavaScript libraries and utilities together to build up a NuPack server as it's by far one of the best ways to distribute client side resources during development.  Some of these libraries I have used myself and thought it might be worth mentioning some of them.

Modernizr

Modernizr is a feature detection library that allows us to test the existence of certain HTML5 features within the browser.  This is not only useful when constructing a page and applying styling of JS widgets but also for detecting things such as WebWorkers, Web DB, application cache etc.  It supports many things,

@font-face, Canvas, Canvas Text, HTML5 Audio, HTML5 Video, rgba(), hsla(), border-image:, border-radius:, box-shadow:, opacity:, Multiple backgrounds, CSS Animations, CSS Columns, CSS Gradients, CSS Reflections, CSS 2D Transforms, CSS 3D Transforms, CSS Transitions, Geolocation API, localStorage, sessionStorage, SVG, SMIL, SVG Clipping, Drag and Drop, hashchange, X-window Messaging, History Management, applicationCache, Web Sockets, Web Workers, Web SQL Database, IndexedDB, Input Types, Input Attributes

In most cases native support for a feature is always better than an alternative CSS hack or JS script.  Rounded Corners are a good example of this.  A lot of, but not all, browsers already support rounded corners natively but in a world where people think a site should be identical in all browsers it is often necessary to provide your own solution.  This means adding extra work for all browsers.  This is where Modernizr comes in.  Rather than applying non-native rounded corners to browsers that support them nativley we can do this,

<script type="text/javascript">
    if(!Modernizr.borderradius){
        $(".borderradius").roundedcorners();
    }
</script>

That way we can always defer to the browser and remove unnecessary processing.  But lets take it step further.  Obviously for the majority of browsers pulling down a rounded corner plugin is completely pointless as it will never be used.  What can we do about that?

Require.JS

Require.JS is one of many module/script loaders available but the good thing about Require.JS is that is extremely simple.  Essentially it injects a script file into the head of the document and fires a callback when ready (there is a bit more configurability held within but that's the gist of it).  So lets take the above example and see what we can do about it.  We don't want to load scripts unnecessarily (lets leave that up to ASP.NET WebForms, ugh.... ) so lets only load the rounded corner script when needed,

<script type="text/javascript">
    if(!Modernizr.borderradius){
        require(["scripts/jquery-corners.js"], function(){
            $(".borderradius").roundedcorners();
        });
    }
</script>

So basically we only get the extra script pulled down in the few browsers that don't support rounded corners, less processing, less traffic (as long as require.js file size < total size of optional scripts). 

Nice.

Obviously you need to be a bit more strategic about where you place this code as you can get FOUC if placed after document has fully loaded.  Another issue is that Require.JS intentionally doesn't support CSS as there is no guaranteed way to ensure it has loaded across all browser.  Thats an easy fix though,

function loadCss(url) {
    var link = document.createElement("link");
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = url;
    document.getElementsByTagName("head")[0].appendChild(link);
}

As always I've put together a nice wee demo app that makes use of these technologies.... coming to a NuPack server near you too.

svn://subversion/Playground/trunk/jameshu/Src/Kainos.Internal.RequireAndModernizr

Let me know if that works as it uses NuPack (but I don't think that is a requirement to open the project).

Published in JavaScript on October 13, 2010