Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect features and lazy-load only the needed polyfills with babel / core-js?

Polyfill services like polyfill.io seem to be delivering only small feature detects to the browser and then lazy-load only the polyfills that are actually needed.

As I understand the babel documentation on polyfilling, babel always include the full set of potentially needed polyfills: it will process a browserslist and then include those polyfills from core-js that the weakest browsers need. A bundler like webpack would then probably merge all these polyfills into the application, but without runtime feature detects.

My application uses modern ES language features but also targets a wide range of browsers, including IE10 and IE11. That requires a lot of polyfills and will probably bloat the bundle, especially for modern browsers that may not need the most of the polyfills.

So I was wondering: can I tell either babel and/or webpack to only include feature detects, split the polyfills off into separate chunks (individually or into small bundles), and then, at runtime, only "lazy"-load what is actually needed?

like image 984
John Goofy Avatar asked Oct 06 '19 20:10

John Goofy


People also ask

Does Babel automatically polyfill?

Babel includes a polyfill that includes a custom regenerator runtime and core-js. This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool. (this polyfill is automatically loaded when using babel-node ).

Do I need Babel polyfill?

So long story short, just using babel is not enough for your application to work because all the latest Javascript features are not supported in all browsers. So to fix this problem, we need to use a polyfill.

How does Babel polyfill work?

Babel Polyfill adds support to the web browsers for features, which are not available. Babel compiles the code from recent ecma version to the one, which we want. It changes the syntax as per the preset, but cannot do anything for the objects or methods used.

How to add a Babel polyfill for IE11?

At first, Babel is looking for target browsers needed to be polyfilled in a configuration file such as .babelrc, .babelrc.json, package.json, or babel.config.js. So if you support IE11, you have to write it like this: useBuiltIns: usage is an option that allows injection of a polyfill based on the files used in your project.

How can I cherry-pick polyfills for specific browsers in Babel?

@babel/preset-env has an option called useBuiltIns. With this option, you can make Babel cherry-pick polyfills for specific browsers: With useBuiltIns: "entry", Babel will replace the import of core-js – the most common polyfill library – with specific polyfills required for browsers you’re targeting.

How to inject core-JS polyfills in the source code?

So far Babel provided three different ways to inject core-js polyfills in the source code: By using @babel/preset-env 's useBuiltIns: "entry" option, it is possible to inject self-installing polyfills for every ECMAScript functionality not natively supported by the target browsers;

What is the difference between core-JS-compact and Babel?

core-js is a library that provides a set of polyfill features. Babel uses core-js-compact and maps it to targeted browsers in order to provide the necessary polyfill feature. So when you target IE11, it’ll map IE11 and provide the polyfill code that IE11 doesn’t support.


1 Answers

Services like polyfill.io investigate your User Agent against a predefined set and based on that provide you with different bundle of polyfills. What you're trying to do is actually way different.

One solution I could thing of is to introduce code splitting into your build (it is on by default in Webpack 4 production build) and create several files in your project, where each would import a different set of polyfills. This will require you to import polyfills manually, but will allow you to have several polyfill chunks, each with a different subset of missing features. After you will have those chunks, you could use some feature detection (probably Modernizr) on the startup of your application and dynamically load only those chunks which are needed by the browser. Keep in mind that this process is rather cumbersome - you will need to take care of including each polyfill manually. Also another disadvantage of it, it will need to make several requests to the server, which will additionally slow down your app start time.

As to other part of your question - webpack/babel will not do the automatic polyfill chunks splitting and runtime feature checking for you, those will need to be handled manually.

like image 171
rafal2228 Avatar answered Oct 03 '22 00:10

rafal2228