简体   繁体   中英

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

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 (ie Promise) you can require it specifically (ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM