Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should Javascript library which uses ES6 and ES7 features require babel-polyfill?

I'm developing a library that use ES6 and ES7 features heavily. Compiling this with Babel results in code, which (naturally) uses primitives such as Symbol or Promise. Should I require('babel-polyfill') to ensure that such primitives are there for sure?

At the first moment, the answer seems to be 'yes' - especially if I don't know on what runtimes someone may execute my lib. On the other hand, if every library does this, we'll end up requiring babel-polyfill over and over again (and I'm not sure if this is a good idea).

like image 750
Tomas Kulich Avatar asked Jan 23 '16 11:01

Tomas Kulich


People also ask

Do you 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.

Why do we need Babel polyfill?

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.

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 ).

What can I use instead of Babel polyfill?

core-js is currently replacing bable-polyfill. You do not have to set it anywhere except for the . babelrc file I have a question, why do you duplicate libraries you have @babel/polyfill and babel-pollyfill the same applies to @babel/preset-env and babel-preset-en .


1 Answers

I did some research on this:

Requiring babel-polyfill from inside the lib looks like anti-pattern; this is for two reasons:

1) babel-polyfill doesn't like to be required multiple times and it will throw, if you try to do this (see note below)

2) doing so will result in a significant increase in the size of a library since you have to bundle the polyfill multiple times.

Both 1) and 2) are relevant only when npm fails to dedupe multiple babel-polyfill dependencies. This can happen if you use older version of npm or deduping might be impossible because of dependency constraints. Since the latest cannot be easily controlled, I consider both 1) and 2) quite serious.

And now, how you (probably) should do it:

If you need a specific feature in your lib (i.e. Promise) you can require it specifically (i.e. not the whole polyfill, just the feature). This approach mitigates 1) and partially mitigates 2).

Probably the best way to do this is simply to warn your users, that your lib expects some ES6 features, so they should require the polyfill.

Nice examples of the first approach is

https://www.npmjs.com/package/promisify-node

which requires it's own version of A+ compatible Promise. Nice example of the second approach is

https://github.com/ubolonton/js-csp

which uses generators, but does nothing to ensure, they are really there (in general, just compiling the code with Babel is not enough and you need to require a polyfill to make them work).

-------- EDIT --------

I found out, that babel-plugin-transform-runtime can be used exactly for this issue: it allows you to use ES6 / ES7 features without poluting the global namespace by requiring polyfill. The sad part of the story is, that this plugin is extremely buggy, probably because it is fundamentally hard to do the job. For example:

Object.keys({})

is transformed to something similar to:

var _keys=require("babel-runtime/core-js/object/keys")
_keys(obj)

but

var aaa = Object
aaa.keys(obj)

does not get transformed at all and therefore will fail (if Object.keys is not defined by neither browser nor polyfill). My advice is - don't use the plugin for this purpose.

like image 58
Tomas Kulich Avatar answered Oct 05 '22 22:10

Tomas Kulich