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).
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.
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.
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 ).
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 .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With