npm Blog (Archive)

The npm blog has been discontinued.

Updates from the npm team are now published on the GitHub Blog and the GitHub Changelog.

guest post: Building Resilient Web Apps

We’re happy to welcome Microsoft to the npm blog for a series of how-to’s targeted at npm Windows users. More than 40% of visitors to the npmjs.com website arrive using the Windows operating system, making Microsoft developers a key audience for npm.

Today’s post by Patrick Kettner points out some tools to simplify staying compatible with every browser environment in which your code might run.

The year was 1995.

Your Humble Narrator wakes up, crushes Ecto Cooler and Dunkaroos, feeds his Tamagotchi, and goes for a quick morning Moon Shoes session. After coming back, he decides to move the hit counter on his link of the Power Rangers webring into its own HTML frame. So he opens the shiny new Windows 95 Start Menu™, and (after a quick game of Oregon Trail) launches Notepad and starts moving it into one of those fancy new frames that Netscape just started supporting. But he hits a snag — a lot of users are still on Lynx and Mosaic. What’s a hip, young developer to do?

User Agent sniff, of course!

perl
my($ua) = $ENV{HTTP_USER_AGENT};

if (index($ua, "Mozilla") > -1) {
   # send framed hit counter 
} else { 
  # send s00per lame non-frame version 
} 

And done — now off to that Kid ’n’ Play concert!

Everything goes great for a while, until this newfangled “Internet Explorer” comes out and ruins the great detection code! IE supports frames, but its user-agent isn’t “Mozilla” so now we have to rewrite our user agent sniff code rather than implement those awesome new table-based layouts everyone is doing! What a bummer.

There’s got to be a better way!

Maybe, rather than knowing which browser supports each feature, and abstracting compatibility from that, we can just query the browser itself to find out…

And for this reason, and this reason alone, JavaScript was created1.

With the power of JS, we can quickly and easily ask the browser if it supports frames, set a cookie, and serve the non-frame version to anyone missing that cookie.

js
if ("frames" in window) {
  document.cookie = ‘frames=true”
}

With that, feature detection was born.

Fast forward two decades:

There are dozens of features added to the browser every year, often in various states of polish and conformity. It’s becoming increasingly difficult to know if the newest and shiniest features are supported in the browser in which your code happens to be executing. Since you’re a code genius and you know that this is a problem that others hit all the time, you reach for a library that already knows all of the edge cases, rather than hand-rolling each one.

Of all of the options out there, Modernizr is by far the most popular way to get this information.

Modernizr

How to install: npm install -g modernizr
External requirements: none

There are hundreds of different things Modernizr will detect for you. Since you’re a responsible web developer, rather than include all of them, you can use the Modernizr package to create custom builds using only the features that you want to support.

The configuration is just a standard JSON file:

json
{ 
  "minify": true,
  "feature-detects": ["canvas"]
}

With that, you can create your very own build of Modernizr as easy as this:

modernizr -c config.json

In addition to the command line interface, there is a programmatic API, so you can require() at will.

There are a lot more features available, so run modernizr --help to see them all.

download service

How to install: npm install <build url>.tar / bower install <build url>.tar
External requirements: none

You may not want to have to install a global bin just to generate this file every time (we have tools for a reason, after all). Modernizr created a hosted downloading service that integrates with npm and bower.

Just grab the build URL found at the top of any generated modernizr file:

screenshot of a modernizr build, higlighting the build url

…and add a .tar.gz to the end of it.

Now you can add that to your package.json (or bower.json), run the requisite install, and you have a built version ready for processing and deployment.

npm install --save https://modernizr.com/download?-cssanimations-csscalc-csscolumns-csstransforms.tar

As convenient as that is, it can be tedious to keep manually adding the features to your config one at a time as you add them. That is why Richard Herrera created the grunt-modernizr and gulp-modernizr packages.

grunt-modernizr

How to install: npm install grunt-modernizr --save-dev
External requirements:Grunt

grunt-modernizr (like gulp-modernizr) uses customizr under the hood to crawl your entire project (.html, .css, .sass, and .js files) looking for references to Modernizr. It dynamically creates the configuration needed for your exact project, and creates the modernizr.js file that suits you best — automagically.

At the end of the day, however, there are some things that you just can’t detect properly on the frontend. Sometimes your only option is to do user-agent sniffing.

useragent

How to install: npm install useragent
External requirements: none

If you truly, 100%, really do need to sniff, then I beg you to not roll your own. There are millions — millions — of different useragents in the wild, all trying to be simultaneously like everyone else and different, too. Rather than rediscover those quirks and edge cases, use a package that has the smarts to handle them all. useragent is one of the fastest, and its data is constantly updated from browserscope.

And if you don’t even want to think about browsers? If you just want to code for the latest browsers and polyfill everything else, FTLabs has just the thing for you

polyfill-service

How to install: npm install polyfill-service (not needed if using hosted version)
External requirements: none

This is mostly intended as a hosted service that you can just include in your web page for free (thanks, FT!)

<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>

The polyfill-service is also a great package you can run yourself. It takes a user-agent and spits out an optimized bundle of polyfilled goodness that makes that browser have the same interfaces as the latest and greatest (or at least as close as it can come).

The web is progressing faster and faster, and there are a ton of new things to play with out there. Whether what you’re writing is just scratching your own itch or will become the Next Big Thing, make sure you’re utilizing all of the tools at your disposal to give your users the best experience possible.

¹ This probably is not actually the reason JavaScript was created.