Babel Pocket Book


Babel Pocket Book — Uplatz

50 deep-dive flashcards • Single column • Presets & Plugins • TS & JSX • Polyfills & browserslist • Build & Performance • Interview Q&A

Readable snippets • Clear mental models • Production-oriented tips

Section 1 — Fundamentals

1) What is Babel?

A JavaScript compiler that lets you use modern JS/TS/JSX today by transforming it to code that runs on your target environments (browsers/node).

npm i -D @babel/core @babel/cli

2) Presets vs Plugins

Plugins transform specific syntax (e.g., optional chaining). Presets are curated plugin bundles (e.g., @babel/preset-env, @babel/preset-react, @babel/preset-typescript).

3) preset-env (the workhorse)

Compiles JS based on your targets (or browserslist). Adds only the transforms needed.

npm i -D @babel/preset-env
// babel.config.js
module.exports = { presets: [['@babel/preset-env',{ targets: ">0.25%, not dead" }]] };

4) Where do configs live?

Project-wide babel.config.js (preferred for monorepos) or per-package .babelrc/.babelrc.json. CLI flags and package.json "babel" field also work.

5) CLI basics

npx babel src --out-dir dist --extensions ".js,.jsx,.ts,.tsx" --source-maps

Use --copy-files to copy non-compiled assets (e.g., CSS).

6) Modules handling

For bundlers (webpack/rollup/vite), set modules:false to keep ES modules for tree-shaking. For Node or plain output, let Babel convert to CJS.

7) Proposal “syntax” vs “transform”

@babel/plugin-syntax-* parses new syntax without changing output (for tooling). @babel/plugin-transform-* compiles it to older JS.

8) Source maps

Generate maps for better debugging; bundlers can consume and re-map them.

npx babel src -d dist --source-maps inline

9) “Loose” mode

Some transforms have loose:true for smaller/faster output with slightly different semantics. Use only if you understand trade-offs.

10) Bugfixes & shippedProposals

preset-env options: bugfixes:true applies Safari/V8 workarounds; shippedProposals:true enables features that are in the spec but not yet widely implemented.

Section 2 — TypeScript, React/JSX, Polyfills & Config

11) TypeScript with Babel

Babel strips types, but doesn’t type-check. Pair with tsc --noEmit for checking.

npm i -D @babel/preset-typescript typescript
// babel.config.js
presets: [['@babel/preset-env'], '@babel/preset-typescript']

12) JSX & React

npm i -D @babel/preset-react
presets: [['@babel/preset-react',{ runtime:'automatic', development: process.env.NODE_ENV!=='production' }]]

“Automatic” runtime removes the need to import React for JSX in React 17+.

13) Next.js / CRA / Vite

These toolchains configure Babel for you. Customize via babel.config.js or framework-specific hooks only when needed.

14) Polyfills: core-js & regenerator

Use @babel/preset-env with useBuiltIns and core-js@3 to inject polyfills based on targets.

npm i -D core-js regenerator-runtime
presets: [['@babel/preset-env',{ useBuiltIns:'usage', corejs:3 }]]

15) @babel/runtime & transform-runtime

Avoid duplicating helpers in every file; use runtime imports.

npm i -D @babel/plugin-transform-runtime @babel/runtime
plugins: [['@babel/plugin-transform-runtime',{ corejs:false }]]

16) browserslist integration

Define targets once in package.json or .browserslistrc; Babel, Autoprefixer, and others read it.

"browserslist": [">0.25%","not dead"]

17) Env-specific overrides

Different builds for dev/prod/test.

module.exports = {
  presets:[['@babel/preset-env']],
  env:{ test:{ presets:[['@babel/preset-env',{ targets:{ node:'current' }}]] } }
};

18) Per-file overrides

overrides:[{ test:/\.tsx?$/, presets:['@babel/preset-typescript'] }]

19) Ignore/only

Speed up builds by excluding generated or external code (e.g., node_modules, dist).

20) Decorators & class fields

These need coordinated plugins and options; align with your framework’s expectations (e.g., TypeScript legacy decorators).

npm i -D @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties
plugins:[
  ['@babel/plugin-proposal-decorators',{ version:'legacy' }],
  ['@babel/plugin-proposal-class-properties',{ loose:true }]
]

Section 3 — Tooling & Build Pipelines

21) Babel + Webpack

Use babel-loader for JS/TS/JSX; set cacheDirectory:true.

npm i -D babel-loader
// webpack.module.rules
{ test:/\.(t|j)sx?$/, exclude:/node_modules/, use:{ loader:'babel-loader', options:{ cacheDirectory:true }}}

22) Babel + Rollup

npm i -D @rollup/plugin-babel
// rollup.config.js
babel({ babelHelpers:'runtime', extensions:['.js','.jsx','.ts','.tsx'] })

23) Babel + Vite

Vite uses esbuild for TS/JS by default; add Babel only when you need Babel-only plugins (macros, special transforms).

24) Library builds

Publish dual ESM/CJS with exports map. Don’t transpile user code; transpile your sources, ship types separately if using TS.

25) Node targets

For server code, target the running Node version to minimize transforms.

presets:[['@babel/preset-env',{ targets:{ node:'20' }, modules:'auto' }]]

26) babel-register (on-the-fly)

Useful for tools/tests. Not for production servers.

require('@babel/register')({ extensions:['.js','.ts','.tsx'] });

27) Caching

Use loader caches and persistent caches (webpack) to speed up rebuilds. Avoid dynamic config that busts cache every run.

28) Minification

Prefer Terser (via bundler). babel-minify exists but is rarely needed in 2025.

29) tree-shaking & sideEffects

Keep ES modules, mark packages "sideEffects": false (or specific files) to enable dead-code elimination.

30) Dynamic import & top-level await

Ensure bundler understands them; Babel parses via syntax plugins if needed.

npm i -D @babel/plugin-syntax-dynamic-import @babel/plugin-syntax-top-level-await

Section 4 — AST, Custom Plugins, Testing & Troubleshooting

31) Programmatic API

const babel = require('@babel/core');
const out = babel.transformSync(code,{ presets:['@babel/preset-env'] });

32) Parsing/Traversing/Generating

const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const t = require('@babel/types');
const generate = require('@babel/generator').default;

const ast = parser.parse(code,{ sourceType:'module', plugins:['typescript','jsx'] });
traverse(ast,{ Identifier(p){ if(p.node.name==='old') p.node.name='next'; }});
const { code: out } = generate(ast);

33) Write a tiny plugin

module.exports = function() {
  return { visitor:{ Identifier(path){ if(path.node.name==='DEBUG'){ path.remove(); } } } };
};

34) Plugin ordering matters

Plugins run first-to-last; presets run last-to-first (inner first). Place syntax plugins before transforms that need them.

35) babel-plugin-macros

Compile-time helpers (e.g., linaria, graphql.macro) without custom config in each app.

npm i -D babel-plugin-macros
plugins:['babel-plugin-macros']

36) Jest + Babel

npm i -D babel-jest @babel/preset-env @babel/preset-react
// jest.config.js
transform:{ '^.+\\.[tj]sx?$':'babel-jest' }

37) ESLint & Type Checking

Babel doesn’t type-check; run tsc --noEmit or vue-tsc in CI; pair with ESLint for style/linting.

38) Common errors

“Support for the experimental syntax …” → missing syntax/transform plugin. “Unknown file extension .ts” → add preset-typescript or loader ext list.

39) Debugging transforms

Use --verbose, BABEL_SHOW_CONFIG_FOR, and babel --config-file to inspect exactly which config applies.

40) Monorepos

Prefer root babel.config.js (not .babelrc) so packages share config; use overrides to tweak per-package.

Section 5 — Performance, Migration, Security & Interview Q&A

41) Performance wins

Limit transforms, keep ES modules, cache aggressively, avoid transpiling node_modules, and pick realistic targets (don’t target IE unless you must).

42) Using SWC/Esbuild with Babel

Many projects compile TS/JS with swc/esbuild for speed and add Babel for React macros or niche plugins.

43) Security & supply chain

Lock dependency versions, audit regularly, and avoid unknown plugins. Treat macros as compile-time code execution.

44) Shipping polyfills safely

Prefer usage-based insertion with core-js@3; avoid global pollution in libraries—document peer polyfills or use @babel/runtime-corejs3.

45) Migrate from Babel 6 → 7+

Replace old preset names (env), add @babel/* scope, re-check decorators/class fields options, and update polyfill strategy to core-js@3.

46) TS-only vs Babel+TS

If you don’t need JSX/many Babel plugins, tsc emit or swc can be simpler. Use Babel when you need React/JSX, macros, or ecosystem plugins.

47) Publishing libraries

Ship ESM (and optionally CJS). Include sourcemaps. Don’t downlevel too far; let consumers decide targets. Document required polyfills.

48) Runtime helpers duplication

If bundle is bloated by helpers, add @babel/plugin-transform-runtime with @babel/runtime and set bundler to externalize it for libs.

49) Troubleshooting “regeneratorRuntime is not defined”

Include regenerator-runtime/runtime or set useBuiltIns:'usage' with core-js+regenerator; or use transform-runtime with regenerator:true.

50) Interview Q&A — Practical

When preset-env? Always for cross-browser builds; it compiles based on browserslist.

Polyfill strategy? useBuiltIns:'usage' + core-js@3 to inject only what’s needed.

Why transform-runtime? Deduplicate helpers and avoid polluting globals, especially in libraries.

TS with Babel? Babel strips types—pair with tsc --noEmit for type-checking.

Decorators gotchas? Align plugin options (legacy vs 2022). Mismatched settings cause runtime errors.