Skip to content
This repository has been archived by the owner on May 11, 2018. It is now read-only.

useBuiltIns: What's the best way to do feature detection before dynamically loading polyfills #141

Closed
mstijak opened this issue Jan 15, 2017 · 7 comments

Comments

@mstijak
Copy link

mstijak commented Jan 15, 2017

I love the idea that apps should load polyfills only if the browser doesn't have all of the required features. This idea is very well explained in these blog posts:

https://philipwalton.com/articles/loading-polyfills-only-when-needed/
https://hackernoon.com/10-things-i-learned-making-the-fastest-site-in-the-world-18a0e1cdf4a7#.xqz6h29mf

babel-preset-env with useBuiltIns is a great way to produce minimal polyfills, however, I cannot find any documentation on how to do client-side feature detection which is required for dynamic loading.

Should this function always be written by hand or this can somehow be automated?

function browserSupportsAllFeatures() {
  return window.Promise && window.fetch && window.Symbol;
}
@hzoo
Copy link
Member

hzoo commented Jan 15, 2017

A good question just never got to think about that yet after #20 but we can refine that now.

cc @keyanzhang @philipwalton

To make this tool even more useful, it could be configurable to accept browser usage data or some sort of browser support matrix, so as usage of legacy browsers declines over time, the polyfills no longer needed are automatically removed without you having to do anything (a strategy currently usage by tools like Autoprefixer for CSS).[3]

I’m not aware of any tools that do this today. If anyone reading wants to build one, I’m sure the community would be eternally grateful!

This is exactly what the useBuiltIns option does right now by replacing require("babel-polyfill") with multiple requires


We can totally automate the 1: checking of the feature 2: the dynamic loading, just not sure about the actual code but I would know how to make it make in the babel plugin once someone can help explain that.

function browserSupportsAllFeatures() {
  return window.Promise && window.fetch && window.Symbol;
}

This part can be easily automated. We can just iterate over the list of requires to generate ^.


I see that this code was explained in the article and we could do it

if (browserSupportsAllFeatures()) {
  // Browsers that support all features run `main()` immediately.
  main();
} else {
  // All other browsers loads polyfills and then run `main()`.
  loadScript('/path/to/polyfills.js', main);
}

function main(err) {
  // Initiate all other code paths.
  // If there's an error loading the polyfills, handle that
  // case gracefully and track that the error occurred.
}

or if we wanted to use require.ensure/System.import/import we could as well. Although since it's a polyfill all the code still needs to be done synchronously or am I missing something here?

@mstijak
Copy link
Author

mstijak commented Jan 15, 2017

Although since it's a polyfill all the code still needs to be done synchronously or am I missing something here?

Loading of polyfills doesn't have to be synchronous. In some cases, it is acceptable to delay main. The assumption is that the majority of users use modern browsers which do not require any polyfills. This optimization targets that group. For the rest, the application would still work.

@spencerhakim
Copy link

Isn't this exactly what Polyfill.io does?

@xtuc
Copy link
Member

xtuc commented Jan 24, 2017

Assume the browser needs Promise, fetch and Symbol, will the browser make three separate request over the network to load the polyfills?

Loading of polyfills doesn't have to be synchronous

I think we need because the would fail in that case:

loadScriptAndEventuallyInject('/path/to/Promise.js');

Promise
  ^^^^^
Promise is not defined

@AndrewIngram
Copy link

AndrewIngram commented Feb 23, 2017

A simple interim step might be an option that lets us exclude any polyfills that are included in polyfill-service/polyfill.io's default set.

The end result is that babel-preset-env provides everything not covered by polyfill.io for those of us who are using it (there are a few such polyfills, which is the main reason i'm currently using both). This doesn't totally guarantee you won't serve up some polyfills that aren't needed, but might reduce the size of the problem.

@stale stale bot added the i: stale label Jun 13, 2017
@stale
Copy link

stale bot commented Jun 13, 2017

This issue has been automatically marked as stale because it has not had recent activity 😴. It will be closed if no further activity occurs. Thank you for your contributions 👌!

@babel-bot
Copy link

This issue has been moved to babel/babel#6635.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants