# A short and simple guide to Babel

> A short guide to Babel: transform modern JavaScript for specific browsers or runtimes with preset-env, Browserslist, the CLI, and webpack.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2018-02-13 | Updated: 2026-07-18 | Topics: [DevTools](https://flaviocopes.com/tags/devtool/) | Canonical: https://flaviocopes.com/babel/

Babel is a JavaScript compiler.

It parses your source code, applies configured transformations, and prints JavaScript that your target environments can run.

You often do not need to configure Babel yourself because a framework or build tool already handles it. Add Babel when your project needs transforms that its existing toolchain does not provide.

## What Babel transforms

Suppose your source contains an arrow function:

```js
const double = (number) => number * 2
```

For a target that does not support arrow functions, Babel can output:

```js
const double = function (number) {
  return number * 2
}
```

The actual output depends on your targets and configuration. Babel should not transform code just because a feature is new. It should transform code when one of your supported environments needs it.

## Install Babel locally

Install the core compiler, command-line interface, and environment preset:

```bash
npm install --save-dev @babel/core @babel/cli @babel/preset-env
```

Keep Babel in the project's development dependencies. A local install makes the expected toolchain part of the project instead of depending on a global command.

## Configure `@babel/preset-env`

Create `babel.config.json` in the project root:

```json
{
  "presets": ["@babel/preset-env"]
}
```

`@babel/preset-env` chooses syntax transforms from your target environments. It is more maintainable than listing individual syntax plugins one by one.

The preset reads Browserslist configuration. Add a `.browserslistrc` file:

```text
defaults
not dead
```

This is only an example. Choose targets from your actual users, support policy, and application requirements.

You can inspect how a query resolves with:

```bash
npx browserslist
```

Read the [`@babel/preset-env` documentation](https://babeljs.io/docs/babel-preset-env/) before using a copied target list. Browser versions in old tutorials become obsolete quickly.

## Compile files from the command line

Compile one file:

```bash
npx babel src/index.js --out-file dist/index.js
```

Compile a directory:

```bash
npx babel src --out-dir dist
```

Add a script to `package.json` for repeatable builds:

```json
{
  "scripts": {
    "build:js": "babel src --out-dir dist"
  }
}
```

Then run:

```bash
npm run build:js
```

The [Babel usage guide](https://babeljs.io/docs/usage/) covers the CLI and other integrations.

## Syntax transforms are not API polyfills

Changing arrow-function syntax is different from adding a missing browser API.

For example, a target might understand the syntax in this code but not provide the `Array.prototype.at()` method:

```js
const last = items.at(-1)
```

Babel's syntax transforms do not automatically implement every missing global, static method, or prototype method.

Polyfills change the runtime environment and can affect bundle size and global behavior. Choose a polyfill strategy for the application and target browsers instead of installing an old all-in-one Babel polyfill package from a tutorial.

The `@babel/polyfill` package is deprecated. Current Babel documentation describes the available polyfill integrations in the [`@babel/preset-env` guide](https://babeljs.io/docs/babel-preset-env/#polyfills).

## Presets and plugins

A plugin performs a specific transformation.

A preset groups plugins and options for a common use case. Official presets include:

- `@babel/preset-env` for JavaScript syntax based on targets
- `@babel/preset-react` for React syntax
- `@babel/preset-typescript` for TypeScript syntax
- `@babel/preset-flow` for Flow syntax

Install only the presets your source needs:

```bash
npm install --save-dev @babel/preset-react
```

Then add the preset:

```json
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}
```

TypeScript's Babel preset removes type syntax but does not type-check the program. Run the TypeScript checker separately when type safety matters.

See Babel's [preset documentation](https://babeljs.io/docs/presets/).

## Use Babel with webpack

Webpack builds the module graph and bundle. Babel transforms JavaScript. Connect them with `babel-loader`.

Install the loader:

```bash
npm install --save-dev babel-loader
```

Add a rule to `webpack.config.js`:

```js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(?:js|mjs|cjs)$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      }
    ]
  }
}
```

`babel-loader` uses the project's Babel configuration. Excluding `node_modules` avoids compiling every dependency unless you know a particular package also needs transformation.

See the current [`babel-loader` documentation](https://webpack.js.org/loaders/babel-loader/) and the [webpack guide](https://flaviocopes.com/webpack/).

## Avoid unnecessary transforms

Broad legacy targets produce more transformed code and may require more runtime support.

Keep target environments explicit, review them periodically, and test the generated build in the oldest environments you promise to support. When a framework owns the Babel setup, use its documented extension points instead of adding a second, competing configuration.
