What are Babel "plugins" and "presets"? (And how to use them)

When working with React, developers will often come across various Babel configurations. You may have seen seen lines like this in a package.json:

// package.json
{
  "babel": {
    "presets": [
      "es2015",
      "stage-0"
    ]
  }
}

Or maybe something like this in a .babelrc:

// .babelrc
{
  "plugins": ["transform-class-properties"]
}

In this post, we'll dig into what exactly stage-x is and why we configure Babel in this way in general. Specifically, we talk about Babel plugins and presets.

We'll start with a quick intro to Babel in case you're only vaguely familiar. If you're already familiar with what Babel is and how it works, skip ahead to the next section, "Babel plugins and presets."

What is Babel?

To understand why Babel exists, we need to dig into a little JavaScript history...

ES5, ES6, ES7, and beyond

JavaScript is the language of the web. It runs on many different browsers, like Google Chrome, Firefox, Safari, Microsoft Edge, and Internet Explorer. Different browsers have different JavaScript interpreters which execute JavaScript code.

Its widespread adoption as the internet's client-side scripting language led to the formation of a standards body which manages its specification. The specification is called ECMAScript or ES.

The 5th edition of the specification is called ES5. You can think of ES5 as a "version" of the JavaScript programming language. Finalized in 2009, ES5 was adopted by all major browsers within a few years.

The 6th edition of JavaScript is referred to as ES6. Finalized in 2015, the latest versions of major browsers are still finishing adding support for ES6 as of 2017. ES6 is a significant update. It contains a whole host of new features for JavaScript, almost two dozen in total. JavaScript written in ES6 is tangibly different than JavaScript written in ES5.

ES7, a much smaller update that builds on ES6, was ratified in June 2016. ES7 contains only two new features.

As the future of JavaScript, we want to write our code in ES6/ES7 today. But we also want our JavaScript to run on older browsers until they fade out of widespread use.

That's where Babel comes in. Babel is a JavaScript transpiler. Babel enables us to write modern JavaScript that will be "transpiled" to widely-supported ES5 JavaScript. We call this process transpiling.

Using Babel

There are a few ways to use Babel in your projects. The simplest and fastest way is to use the package babel-standalone. You can include it in a script tag like this:

<script
  src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.18.1/babel.min.js"
></script>

Now, Babel will automatically transpile any script tags with type text/babel or text/jsx:

<div id="output"></div>

<script type="text/babel">
const getMessage = () => "Hello World"; // ES6!
document.getElementById('output').innerHTML = getMessage();
</script>

Projects like create-react-app automatically include and configure Babel for you, so you can use a sane Babel configuration out-of-the-box to write React components.

Babel plugins and presets

In Babel, a preset is a set of plugins used to support particular language features. The two presets Babel uses by default:

  • es2015: Adds support for ES2015 (or ES6) JavaScript
  • react: Adds support for JSX

Remember: ES2015 is just another name used for ES6. We let Babel use the default es2015 preset for this project because we don't need or use either of ES7's two new features.

Beyond ES7, proposed JavaScript features can exist in various stages. A feature can be an experimental proposal, one that the community is still working out the details for ("stage 1"). Experimental proposals are at risk of being dropped or modified at any time. Or a feature might already be "ratified," which means it will be included in the next release of JavaScript ("stage 4").

From the Babel docs:

The TC39 categorizes proposals into the following stages:

  • stage-0 - Strawman: just an idea, possible Babel plugin.
  • stage-1 - Proposal: this is worth working on.
  • stage-2 - Draft: initial spec.
  • stage-3 - Candidate: complete spec and initial browser implementations.
  • stage-4 - Finished: will be added to the next yearly release.

We can customize Babel with presets and/or plugins to take advantage of these upcoming or experimental features.

Which plugins or presets are "safe" to use with React?

Babel warns that anything pre stage-3 should be used with caution.

In our book, we generally avoid features that are experimental. This is because we don't want to teach features that might be modified or dropped.

You might find that you and your team are attracted to some experimental JavaScript features. Indeed, certain experimental features are popular among the React community. The "property initializers" feature is widely used because it makes declaring React ES6 class components "cleaner."

In deciding if you want to follow suit with certain bleeding-edge trends in your own projects, you might find comfort in tools like react-codemod. If, for instance, the property intializers proposal were to be dropped or modified, it is guaranteed that tooling would be available to automatically convert your codebase's React components to conform to the new spec. Depending on which experimental features you decide to use, it's safe to say the risk of your codebase becoming "outdated" due to a dropped experimental feature is mitigated.

What's more important is ensuring everyone on your team is using the same style and JavaScript feature set and composing React components in a way that new developers can quickly pick up.

How to use Babel plugins and presets

There are two primary ways to configure Babel. The first is in package.json. You can list plugins and presets like this:

// package.json
{
  "babel": {      // nest config under "babel"
    "presets": [
      "es2015",
      "react",
      "stage-3"
    ],
    "plugins": ["transform-class-properties"]
  }
}

The second is in a separate file at the root of your project, .babelrc:

// .babelrc
{
  "presets": [
    "es2015",
    "react",
    "stage-3"
  ],
  "plugins": ["transform-class-properties"]
}

We recommend the .babelrc approach.

Remember: In the default Babel setup, es2015 and react are automatically enabled -- no configuration needed.

If you're curious to see a live example of a Babel plugin in-action, check out our article on property initializers. If you want to see how to make a custom Babel plugin, the Relay chapter in our book dives into this.

For more info on the available plugins and presets and how to configure them, check out the the Babel docs.


Because you found this post helpful, you'll love our book — it's packed with over 800 pages of content and over a dozen projects, including chapters on React fundamentals, Redux, Relay, GraphQL, and more.


Anthony Accomazzo

Passionate about teaching, Anthony has coached many beginning programmers through their early stages. Before Fullstack React, he led the development of IFTTT's API platform. A minimalist and a traveler, Anthony has been living out of a backpack for the past year.