Progressive Web App Experiment: Promyfill

Jad Joubran
Progressive Web Apps
4 min readJun 1, 2017

In modern web development, we’re eager to use the latest features. For example, I love using the new fetch API. I remember back when it wasn’t supported on Safari, I didn’t want that to stop me. So I grabbed developit/unfetch’s 500 bytes bare minimum fetch polyfill. I loved it because I didn’t need to worry about its impact.

However, there are scenarios where you must use a more “complete” polyfill, for example github/fetch. That’s when I started wondering if there are asynchronous ways of loading polyfills only when they’re needed.

The problem with loading polyfills

Generally, there have been two main approaches of loading polyfills:

I) Always load all polyfills

Let’s say you’re working with the new IntersectionObserver API, which is not supported on all browsers yet.

Your only choice would be to include a Polyfill. Now, for obvious reasons, the polyfill would only execute if the IntersectionObserver API is not natively implemented in the browser.

However, what we often forget about is that we’re still shipping around 7kbs of JavaScript. In some scenarios this is fine, but if you’re building a Progressive Web App we probably want to reconsider how we’re loading polyfills.

II) Block until conditional polyfills are loaded

Polyfill.io provides an amazing service of conditionally returning relevant polyfills based on your User Agent string. This means it will only load the fetch polyfill on browsers that don’t have it.

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

You can also specify to conditionally load specific polyfills rather than including all of them.

Polyfill.io is used by multiple major websites at the moment, and is probably the Production-ready way of loading polyfills.

However, even on a latest browser, we have to wait for that polyfill.min.js request to finish before our app is able to boot. This means when the internet is slow on the first visit, we’re going to get slower page load.

Luckily, Polyfill.io allows you to run a callback once the polyfill has finished, potentially solving this issue.

<scrip async defer src=”https://polyfill.io/v2/polyfill.min.js?callback=polyfillsAreLoaded">

This approach makes more sense if you’re able to use it. Try not to block all your scripts while waiting for polyfills.

Now this solution might not be ideal for everyone. So this is when I started working on an experiment tailored for PWAs which aims to solve this problem.

Introducing Promyfill

Simply put, Promyfill is a Promise based Polyfill that only loads a polyfill when needed. Promyfill is obviously meant for smaller projects, mainly PWAs, willing to take advantage of modern Web APIs, without shipping additional bytes or blocking on polyfills to newer browsers.

passing “fetch” as an argument to then is optional

Let’s break down the code and see how it works.

'fetch' in window will return either true or false depending if the browser natively supports fetch or not.

  • If it returns true, then promyfill will immediately resolve and we’ll be able to run our code that’s using fetch.
  • If it returns false, then promyfill will inject an async script that’s going to load the polyfill you specified. When this script tag loads, promyfill is going to resolve and we’ll be able to run our code that’s using fetch.

Using this approach gives us the ability to reward our users on modern browsers. If fetch is available, promyfill immediately resolves, which means there’s no delay for us to execute our fetch powered code.

Now if the browser does not natively support fetch, instead of delaying the entire execution of our javascript file, we’re able to delay only the fetch dependent code until the polyfill has been loaded.

The best part about promyfill is that it has a tiny footprint (less than 500 bytes) as we’re working towards shipping less JavaScript.

Network trace

Here’s a network trace on browsers in both scenarios.

Browsers with fetch support
Browsers without fetch support

Notice how on browsers that don’t have fetch support, fetch is loaded right before executing the block of code that relies on fetch.

Demo link

Advanced use cases

It’s probable that your web app will use fetch more than once. This is when a differed makes a lot of sense.

And it gets better with async/await!

Promyfill example with async/await

Feedback

This is one of many PWA experiments that I’ve been working on.

Enjoy it and let me know in the comments if you have any feedback.

Checkout my interactive JavaScript course: learnjavascript.online

--

--