Transpilation
This lesson explains Transpilation with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.
ES6+ Transpilation Overview
Transpilation is the process of converting modern JavaScript into
older JavaScript that more browsers can understand. It lets
developers write ES6+ syntax such as arrow functions, classes,
modules, and async/await while still supporting older runtime
environments.
Transpilers such as Babel do not usually change what your code
does. They rewrite syntax into an equivalent older form. This is
different from polyfills, which add missing runtime features such
as Promise or Array.prototype.includes().
| Feature | Description |
| Process Name | Transpilation |
| Popular Tool | Babel |
| Input | Modern JavaScript (ES6+) |
| Output | Older compatible JavaScript |
| Common Preset | @babel/preset-env |
| Common Uses | Browser support, legacy apps, library publishing |
Basic Transpilation Example
// Modern source code
const greet = (name) => {
return `Hello, ${name}!`;
};
console.log(greet("Alex"));
// Transpiled output (simplified)
var greet = function greet(name) {
return "Hello, " + name + "!";
};
console.log(greet("Alex"));
An arrow function with a template literal can be rewritten into a
standard function and string concatenation. The behavior stays the
same, but the output works in older browsers.
How Transpilation Works
A transpiler reads your source code, converts it into an abstract
syntax tree, applies plugins and presets, and then generates new
JavaScript code. Build tools such as Vite, Webpack, and Rollup
often run Babel automatically during development and production
builds.
| Step | Description | Example |
| Write Modern Code | Use ES6+ syntax in source files. | const total = items.map(...) |
| Configure Babel | Choose presets and target browsers. | @babel/preset-env |
| Run Transpiler | Convert source to compatible output. | npx babel src --out-dir dist |
| Add Polyfills | Fill missing runtime APIs if needed. | core-js |
| Bundle App | Ship final JavaScript to browsers. | vite build |
| Test Targets | Verify support in required browsers. | browserslist |
Transpilation vs Polyfills
| Feature | Transpilation | Polyfill |
| What It Changes | Syntax in your source code. | Missing runtime APIs. |
| Example Input | const x = () => 1; | Promise, fetch() |
| Example Output | var x = function() { return 1; }; | Shim implementation added at runtime |
| Best For | Arrow functions, classes, modules. | New built-in methods and globals. |
Basic Babel Configuration
{
"presets": [
[
"@babel/preset-env",
{
"targets": "defaults"
}
]
]
}
Babel presets group common transformation rules.
@babel/preset-env is the most common choice because
it converts modern syntax based on your target browsers.
Target Browsers with Browserslist
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"last 2 versions",
"not dead"
]
}
}
]
]
}
# .browserslistrc
last 2 versions
not dead
> 0.5%
IE 11
Browserslist tells Babel which browsers you support. Babel then
transpiles only the features those browsers cannot run natively.
Transpile a Class Example
// Source
class User {
constructor(name) {
this.name = name;
}
greet() {
return `Hi, ${this.name}`;
}
}
const user = new User("Alex");
console.log(user.greet());
// Transpiled output (simplified)
function User(name) {
this.name = name;
}
User.prototype.greet = function greet() {
return "Hi, " + this.name;
};
var user = new User("Alex");
console.log(user.greet());
ES6 classes are syntactic sugar over constructor functions and
prototypes. Babel rewrites them for environments without native
class support.
Transpile async/await
// Source
async function loadUsers() {
const response = await fetch("/api/users");
return response.json();
}
loadUsers()
.then((users) => console.log(users))
.catch((error) => console.error(error));
// Transpiled output (simplified)
function loadUsers() {
return _asyncToGenerator(function* () {
const response = yield fetch("/api/users");
return response.json();
})();
}
async/await is converted into generator-based helper
code or Promise chains. This often requires both transpilation and
a Promise polyfill for very old browsers.
Add Polyfills with preset-env
{
"presets": [
[
"@babel/preset-env",
{
"targets": "defaults",
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
// Source
const total =
[1, 2, 3].includes(2);
console.log(total);
With useBuiltIns: "usage", Babel can inject only the
polyfills your code actually needs, such as
Array.prototype.includes(), instead of loading all of
core-js.
Common Transpilation Use Cases
- Supporting older browsers while writing modern JavaScript.
- Using ES modules, classes, and async/await in legacy projects.
- Publishing libraries that must work across many environments.
- Standardizing syntax across teams and codebases.
- Preparing code for production bundlers and minifiers.
- Gradually upgrading old JavaScript applications to ES6+.
Transpilation Best Practices
- Define browser targets clearly with Browserslist.
- Use
@babel/preset-env instead of transpiling everything manually. - Separate syntax transpilation from runtime polyfills in your mental model.
- Prefer
useBuiltIns: "usage" to avoid unnecessary polyfills. - Test output in your minimum supported browser, not only modern Chrome.
- Let your bundler handle Babel during build when possible.
- Keep source code modern and readable; do not write for the transpiled output.
Common Transpilation Mistakes
- Assuming transpilation alone fixes all browser compatibility issues.
- Forgetting polyfills for missing runtime APIs.
- Transpiling to ES5 when your target browsers support modern syntax.
- Shipping huge polyfill bundles without checking actual usage.
- Not defining browser targets and over-transpiling by default.
- Debugging transpiled output instead of readable source code.
- Confusing TypeScript compilation with JavaScript polyfilling.
When Transpilation Is Less Needed
| Scenario | Why Transpilation May Be Minimal |
| Modern browser-only apps | Latest Chrome, Firefox, Safari, and Edge support most ES6+ features. |
| Node.js backends | Recent Node versions support modern syntax natively. |
| Internal tools | Controlled environments reduce legacy support needs. |
| Framework defaults | Build tools may already optimize targets for you. |
Key Takeaways
- Transpilation converts modern JavaScript syntax into older compatible syntax.
- Babel is the most common transpiler in the ES6+ ecosystem.
@babel/preset-env and Browserslist control what gets transformed. - Polyfills are still needed for missing runtime APIs in old browsers.
- Write modern source code, configure targets carefully, and test real browser support.
Pro Tip
Think of transpilation as syntax conversion and polyfills as runtime
patching. Most real-world ES6+ projects need both, but only for the
browsers and features they actually support.