My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Tuesday, March 18, 2014

Do Not Require Polyfills

I'll try to keep it as simple as it sound, polyfills should never be a dependency and here is why:

Do Not Confuse Polyfills With Libraries

If you are using any utility library that brings you something similar to requestAnimationFrame under a different namespace that is not the window or the global object, that is not a polyfill but rather a library you have dependencies based on, and this is OK!

Polyfills Do Not Want Maintenance

Indeed, polyfills are scripts usually placed upfront the main application that should be removed when time is right, which means ASAP, without requiring indirectly any update, upgrade, or change from your own module.

Polyfills Aren't Virtually Needed

You don't want to require('latest-browser-or-nodejs'); in your code, because that is pointless, no matter if you use a UMD or a browserify approach, no module should contain a polyfill and here is why:

Global Pollution

Yes, polyfills are usually greedy because being polyfills they fill the environment gap, where the environment is usually not confined in your own closure.

Deadly Obtrusive

If your module defines its logic behind some feature detection and including another module could change this, you are basically dropping an undesired bomb in your system you were not aware of the moment your module acted as it should ... as module, library, whatever it is, that didn't include a bloody obtrusive AMD that changed everything the module knows before that ... I mean, the moment your module is defined, that's the env you expect.

Always Upfront!

Polyfills should have the exclusive position on top of anything you are developing because the day you won't need them you'll simply drop them and everything else will keep working lighter and faster.
Making your polyfill usable as a module won't benefit anything based on it for the simple reason that such modules won't be portable without a potentially not needed/necessary anymore environment normalizer, and need at that time extra maintenance form something assumed to work as that in such environment.

Delegate Dependencies

If your module depends on some polyfill just say so ... any other module that depends on your one might need or rely same polyfill too so don't make such polyfill your own choice .. and once again, if it does not change globally the behavior, it's NOT a polyfill ... in such case, feel free to include it!

What About browserify ?

It's OK to publish modules to npm or bower so that it's possible to create a build task that will include polyfills in the right order, if needed, using require('es5-shim') and require('dom4') and others upfront.
However, if you did the mistake to wrap your polyfill inside an UMD and the define library is around, being the inclusion of modules completely arbitrary in terms of order, you might cause troubles not only for your own logic, but also for all other modules that were expecting, as example, the window.TCPSocket to be there. Fix it dropping any UMD logic around your polyfill, and publish again ;-)


sbruchmann said...

It seems like you misspelled requestAnimationFrame.

Andrea Giammarchi said...

thanks :-)

Andrea Giammarchi said...

anything that is not confined in its own closure does not make sense to exists as AMD module ... so polyfills upfront so these can be dropped when not needed anymore and without AMD since this is obtrusive behavior because it changes the whole realm.

No excuses, if it's a polyfill, it should be upfront and no module should depend on it so that you can drop that polyfill as soon as it's not needed anymore.

As easy as that, any excuse sounds just a bad practice without concrete reasons or benefits: AMD is not meant to be used to polyfill, libraries and modules are ... not partial or full polyfills.

Andrea Giammarchi said...

also, polyfills as modules can be the most pointless thing ever if the requiring order is late for other modules that would like to rely on the same polyfill ... if you need to include as default with all modules than you are wasting time and bytes because that's a polyfill, it should be already there or not there at all in new environments so do NOT include it because tomorrow might not be needed ;-)

kentaromiura said...

Sorry it wasn't clear you were referring to AMD, after a second read I understood your point, if code is relying on feature detection and runs before any polyfill you look for trouble indeed.
I was thinking more broadly to cjs cases where the order is always correct(unless you defer).