Polyfill JavaScript Only When You Need To

Share this:

The following is a guest post by Pascal Klau, a trainee from South Germany, who dislikes unnecessary HTTP requests and broccoli. Pascal is going to explain way to use a polyfilling service in such a way that you might get away with not using it at all.

The Situation

We want to write JavaScript in the ES6 syntax. But since we need to support older browsers that don't understand ES6, we need to deal with that.

Here the standard procedure: Write ES6 → compile everything down to ES5 (e.g. Babel) → send that to the browser.

This may not be the most efficient way anymore. The problem is that we're forcing modern browsers to run the old code when they don't have to. They support ES6, so can't we give them ES6.

A Better Way

There is a polyfill project called Polyfill.io API that can polyfill ES6 code client side.

It also implements polyfills for some HTML features like the <picture> element.

Description from their website:

Polyfill.io reads the User-Agent (UA) header of each request and returns polyfills that are suitable for the requesting browser. Tailor the response based on the features you're using in your app [...]

It is being developed by Financial Times, so it has some support and we can be fairly confident it's not going to disappear on us.

One thing to be clear on: Polyfill.io does not provide support for syntactic sugar. For example, Classes, enhanced Object Literals, and things like Arrow Functions. You'd still need a compiler for those.

Set up Polyfill.io

Adding Polyfill.io to your project can be this simple. Add the CDN-hosted script to your page:

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

Running the script spits out the UA and what features you want.

UA detected: chrome/56.0.0
Features requested: default

Change request parameters

There are a bunch of options to customize the request which you put into the script source.

Features

List of browser features to polyfill. Accepts a comma-separated list of feature names. Available feature names are shown on the Browsers and Features page.

Callback

Name of a function to call after the polyfills are loaded. It is simply a way of triggering your own code when the polyfills have loaded, intended to allow the polyfill service to be more easily loaded asynchronously with async and defer attributes.

The Problem

As good as all this sounds, it is still not perfect.

Modern browsers do not have to load ES5 now, but instead have to make a server roundtrip (an HTTP Request) to check if polyfills are needed.

This bugged me so much that I worked on a little project to help.

An Even Better Way

Set up dynamic polyfill

The npm package I created is called dynamic-polyfill. It checks whether the feature is natively supported or not before making any server request.

Share this:

Comments

This article seems kind of odd. It talks about writing with “ES6 syntax” but then goes on to talk about “polyfilling features.” No amount of polyfilling, however targeted, will get you arrow functions, const, let, or other syntax in older browsers.

I’m extremely confused by this as well. So what do we do with the ES2015+ syntax? Do we still compile that, but somehow without ES2015+ libraries bundled in? But then how do we make that work with module loaders? :X

What might be really cool is a way to load ES2015 code directly in supporting browsers (syntax and all) while still delivering ES5 for non-supporting (or partially-supporting) browsers. Still not sure how module loaders would work, though. And it would double the debugging effort, since there are two different execution paths depending on support or lack thereof.

I think there is a confusion here between ES6 syntax, which can’t be polyfilled and will throw errors on older browsers, and new JS API which can be polyfilled.
If you want to support older browsers, you can’t skip the ES6 to ES5 transpiling.

This seems completely useless to me. So you waste an extra http request to go and ask a third party API for polyfills for Array.values or String.contains, but you still have to code in ES5, i.e. without arrow functions, default parameters, destructuring, etc etc. With the risk that if their site is down or just slow you are screwed.

Why don’t we just do feature detection and trigger differential loading of a transpiled or ES6 library dynamically? This could be a polyfill in the root document (if doing an SPA, else this is going to be more convoluted), so we don’t need to waste precious requests.

👋

CSS-Tricks* is created, written by, and maintained by Chris Coyier and a team of swell people. It is built on WordPress and powered up by Jetpack. It is made possible through sponsorships from products and services we like.