Progressive Web App Experiment: Promyfill
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.
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 usingfetch
. - 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 usingfetch
.
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.
Notice how on browsers that don’t have fetch support, fetch is loaded right before executing the block of code that relies on fetch.
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!
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