Babel-polyfill and babel-runtime easily explained

If you have worked with Babel before, no doubt you came a cross these two packages: babel-polyfill and babel-runtime

Basically these two modules do the same thing: emulate an ES2015 environment but in a different way.

In this article I will explain the difference between these two and when you should use one or the other.

Babel logo


This module accomplishes emulating ES2015 by assigning methods on the global (like: Promise and WeakMap) and to prototypes (like Array.prototype.includes). For example: if your environment doesn’t have a Promise object, once you require babel-polyfill, you know have the Promise object, because it was added to the global scope.


This module does something very similar, but it doesn’t change the global namespace or pollute prototypes. Instead, babel-runtime can be included as a dependency of your application, just like any other module, and you can include the ES2015 method from the module.

This however, is too much work, so we use babel-plugin-transform-runtime which we can add to our babel config to automatically rewrite your code such that you write your code using the Promise API and it will be transformed to use the Promise-like object exported by babel-runtime.

More information about setting it up can be found here.

So when to use what?

  • If you don’t care about polluting the global scope, babel-polyfill is the better option: the runtime does not work with instance methods such as myArray.includes(15).
  • If you are writing a public module: use babel-runtime
  • If you are writing an app then babel-polyfill is the better option
  • There will be cases, when you don’t need either of these, if you’re writing a library where size matters, you may be better of avoiding them.