Giter VIP home page Giter VIP logo

poly-poly's Introduction

poly-poly

Element to load feature polyfills from polyfill.io service.

Helps to follow fundamental polyfill best practices and avoid bundling polyfills with your elements while still supporting the PRPL pattern.

Background

Let's talk about polyfills ... they are never going to go away. The whole reason we can use WebComponents at all is because polyfills enable them in browsers that don't yet support them. If we had to wait for all browsers to support a feature before we could use it, some features would never be usable because use helps drive implementation by other browser vendors and the polyfills help with that.

We obviously need to load the WebComponents polyfill itself when using Polymer but what about other polyfills for features that may be required by individual elements?

The Problem

The problem is, who's job is it to load polyfills and how?

One option is for each element to load whatever polyfill it needs directly. It's easy to add a static <script src="some-polyfill.js"> to the element and boom, job done. But there are some drawbacks to doing this:

  1. Polyfill scripts need to be added to each element repository (and not all are available via package managers). Does the element author have to maintain those scripts as they are updated and improved? Will they?

  2. Polyfill scripts are loaded by all browsers, whether they need them or not. Some polyfills are small and insignificant but others can be pretty large and they all add-up and ultimately consume bandwidth and add script parsing overhead which can be significant on slower devices.

  3. Different elements could need the same polyfills or different combinations of polyfills which would further add to waste, especially as the same scripts could then be referenced from several different paths.

  4. It's unclear when polyfills can be removed. For a published element it becomes a hard choice to support some versions of browsers or not. All these polyfills in different elements could build up over time.

  5. We may be forcing one particular polyfill on consumers of our element when they would prefer to use a different implementation.

Some of these could be mitigated - the element could include some feature detection to only load the polyfill if it was required but this then leads to other problems - making sure that the now possibly unreferenced script is included in any app bundle and so on. If we end up using several different polyfills in different elements, each will add some latency to the loading which could be undesirable. We're also still left with the polyfill versioning and support issues.

Bundling polyfills with our element goes against fundamental polyfill best practices

There's also some similarities to The Problem With Using HTML Imports for Dependency Management

Use a Polyfill Service

The ideal solution to polyfill loading is to use a polyfill service. This can allow us to update the users browser to support just the features we require all in a single web request and as browsers are updated, the use of the polyfills can evaporate to zero all without a single code change or redeploy of our applications.

If our element used any new feature we would need to document it and it become the app authors responsibility to load any required polyfill for it based on the browsers they want to support.

Perfect!

Except ...

Async Polyfill Loading

Our polyfills may be requested way up in the header of the page, but the elements that use them are right down in the DOM. If we make everything load synchronously then we're OK but it would be nicer if we could keep everything as async as possible and only load them if and when they are required.

If the elements and polyfills are loaded async, there is no guarantee that the polyfills will have patched the browser features before our elements try to use them. So how do we make them wait if they have to?

In some ways, this is more of a challenge with Polymer and WebComponents because they are so "native". With many other frameworks there is a much clearer point where the app is loaded and initialized so, if you are loading polyfills, you can just delay that startup. But if you have native support for WebComponents and you want to initialize the rest of your app while the polyfills are loaded, you need some way to make them wait.

So I tried to come up with a solution ...

Any element that requires polyfills should inludes a dependency on the poly-poly.html element. This generates a request to the polyfill.io service to load whatever polyfills have been listed in the window.PolyPoly.features array. This array should be set based on feature detection in the apps index.html page.

This will delay triggering any polyfill loading until an element that requires it is itself loaded which should make the system lazy-loading / PRPL pattern friendly. i.e. if only certain pages of an app need polyfilled features then the polyfills do not need to be loaded unless and until those pages are.

The poly-poly element provides a promise that the calling element can use to delay any operations until the polyfilled features are available. Actually, it's not a real Promise - I didn't want to load the promise-polyfill that would load regardless of the browsers existing support (which is the whole point of this element) so it's Promise-like ... just enough to provide a .then() callback.

An example of the "promise" being used to delay functionality of an element until the required feature is available is shown in lazy-img which requires the newer IntersectionObserver which at the time of writing is only supported natively in Google Chrome.

With Chrome, no additional scripts are loaded. Using a browser without native support will make a request to load the ~20Kb polyfill required to function.

Final Thoughts

The idea scenario would be for as much of this to be automated and built in to tooling as possible. Maybe elements could be tagged with the features that they use (or they be automatically detected by an analyzer) and the script to load them generated automatically.

I'd love to hear feedback on the approach and any ideas to improve it.

poly-poly's People

Contributors

captaincodeman avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.