# What Is Transpiling and How Does Babel Enable Modern JavaScript in Old Browsers?

> Understand transpiling, the process of converting modern JavaScript to browser-compatible code. Learn how Babel enables new features in older browsers, ensuring wide accessibility.

- Repository: [Kyle Simpson/You-Dont-Know-JS](https://github.com/getify/You-Dont-Know-JS)
- Tags: deep-dive
- Published: 2026-02-24

---

**Transpiling is the process of converting JavaScript source code written with the latest language features into an equivalent version that uses only syntax supported by older JavaScript engines, allowing developers to write clean, expressive code while ensuring compatibility with legacy browsers.**

According to the *You-Dont-Know-JS* repository by Kyle Simpson, transpiling solves the fundamental problem of code compatibility in a fragmented browser ecosystem. The concept is introduced in [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md) (lines 216-227), where the author explains that while new JavaScript syntax offers better expressiveness, older engines throw syntax errors when encountering unrecognized tokens like `let` or arrow functions.

## Understanding Transpiling in JavaScript

**Transpiling** acts as a source-to-source compiler. Unlike traditional compilation that transforms high-level code into machine code, transpiling keeps the output as human-readable JavaScript—just an older dialect of it. This distinction matters because the resulting code ships to browsers exactly as text, not binary.

The *You-Dont-Know-JS* text emphasizes that transpiling runs **before** deployment. In [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md) (lines 249-250), the author describes the **target** environment as a "sliding window" that shifts upward as you drop support for obsolete browsers. This means your Babel configuration evolves with your user base rather than remaining static.

### How Babel Transforms Code

Babel operates through a three-stage architecture that processes modern JavaScript:

1. **Parsing** – Babel reads the source code and constructs an **Abstract Syntax Tree (AST)**, a hierarchical representation of the code's structure.
2. **Transforming** – Plugins traverse the AST, identifying modern syntax nodes (e.g., `let` declarations, arrow functions, or async/await) and rewriting them into equivalent ES5 constructs.
3. **Generating** – Babel prints the modified AST back into a new source file containing only syntax your target browsers understand.

This pipeline ensures that browsers never encounter unsupported syntax; they receive only the transpiled output.

## Transpiling in Action: A Practical Example

The *You-Dont-Know-JS* repository provides concrete before-and-after code samples in [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md) (lines 221-228 and 332-342) that demonstrate how Babel rewrites block-scoped declarations.

### Modern ES6 Source Code

Consider this snippet using ES6 `let` declarations for block-scoped variables:

```js
if (something) {
    let x = 3;
    console.log(x);
} else {
    let x = 4;
    console.log(x);
}

```

*This source appears in [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md) at lines 221-228.*

In modern engines, each `let x` is scoped to its respective block (the `if` or `else` branch). However, older browsers lack block-scoping support for `let`, causing syntax errors or unexpected behavior.

### Babel-Generated ES5 Output

Babel transforms the above into `var`-based code that simulates block scoping through variable renaming:

```js
var x$0, x$1;
if (something) {
    x$0 = 3;
    console.log(x$0);
} else {
    x$1 = 4;
    console.log(x$1);
}

```

*This transpiled output appears in [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md) at lines 332-342.*

Notice that Babel renamed the two `x` variables to `x$0` and `x$1` to prevent the variable hoisting and collision issues that `var` would otherwise cause. The functional behavior remains identical, but the syntax is now compatible with ES3/ES5 engines.

## Configuring Babel for Production

To implement the "sliding window" target strategy mentioned in [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md) (lines 249-250), you configure Babel through `.babelrc` or [`babel.config.js`](https://github.com/getify/You-Dont-Know-JS/blob/main/babel.config.js). The `@babel/preset-env` preset automatically determines required transformations based on your specified browser support matrix:

```json
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "browsers": ["> 0.25%", "not dead"]
      }
    }]
  ]
}

```

This configuration tells Babel to only transpile features missing from browsers representing more than 0.25% of global usage and excluding explicitly "dead" browsers (like Internet Explorer 10). As your analytics show older browsers fading away, you tighten these targets to output cleaner, more modern code while maintaining compatibility.

## Summary

- **Transpiling** converts modern JavaScript syntax into older equivalents through source-to-source transformation, not machine code compilation.
- **Babel** implements this via an AST-based pipeline: parsing, transforming with plugins, and regenerating code.
- The **target environment** operates as a "sliding window" where you adjust Babel presets as you drop legacy browser support.
- In [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md), the transformation of `let` into renamed `var` declarations demonstrates how Babel preserves block-scoping semantics without requiring native engine support.

## Frequently Asked Questions

### What is the difference between transpiling and polyfilling?

**Transpiling rewrites syntax** (e.g., converting `let` to `var` or arrow functions to regular functions) so the parser doesn't throw errors, while **polyfilling injects runtime behavior** (e.g., adding a `Promise` implementation or `Array.prototype.includes` method) for missing APIs. According to the *You-Dont-Know-JS* text, you often need both: Babel handles new syntax, while core-js or similar libraries handle missing methods.

### Does transpiled code run slower than native modern JavaScript?

**Potentially, but rarely significantly.** Transpiled code may include helper functions or verbose workarounds (like the `x$0` and `x$1` renaming shown in [`get-started/ch1.md`](https://github.com/getify/You-Dont-Know-JS/blob/main/get-started/ch1.md)) that add slight overhead compared to native engine implementations. However, the difference is usually negligible compared to the cost of network transmission and parsing; the compatibility benefit outweighs micro-optimizations unless you're transpiling hot paths in performance-critical loops.

### Can Babel transpile TypeScript or JSX?

**Yes, through specialized presets and plugins.** While the *You-Dont-Know-JS* examples focus on ES6-to-ES5 transpiling, Babel's plugin architecture extends to TypeScript (`@babel/preset-typescript`) and JSX (`@babel/preset-react`). The same AST-based pipeline applies: parse the non-standard syntax, transform it into standard JavaScript, and generate output that browsers can execute.

### How do I debug original source code when browsers run the transpiled version?

**Use source maps.** When Babel generates the transpiled output, it can produce accompanying source map files (or inline source maps) that map the generated code back to the original source lines. Configure your build tool to generate these maps, then enable "Enable JavaScript source maps" in browser DevTools. This allows you to set breakpoints and view stack traces against your original ES6+ code rather than the renamed variables and transformed syntax.