Configuring Babel for JavaScript Transpilation
Modern JavaScript with ?. and ?? operators doesn't work in Internet Explorer 11. JSX and TypeScript also require additional processing. Babel solves these problems: it transforms modern code into syntax understood by older browsers and transpiles JSX, TypeScript, experimental TC39 proposals, and decorators. We have configured Babel for dozens of projects—from landing pages to large SaaS platforms. A proper configuration reduces bundle size by 20% and speeds up page loading. In this article, we'll break down a production-ready configuration.
What You Need to Know Before Configuring
Modern frontend builds rarely do without Babel. Even if you use SWC for speed, Babel remains essential for complex AST transformations and custom plugins. Our experience shows that a correctly configured Babel reduces debugging time for legacy browsers by 30% and cuts maintenance costs through precise polyfill selection. It's important to understand the difference between presets and plugins—presets are sets of plugins, and plugins perform specific AST transformations.
How to Configure Babel: Step by Step
Installation and Basic Configuration
Install dependencies with one command:
npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-react @babel/preset-typescript @babel/plugin-transform-runtime @babel/runtime Create babel.config.json in the project root. Below is a ready config for a modern frontend with React and TypeScript. Note the env section: it overrides settings for the test environment.
{ "presets": [ [ "@babel/preset-env", { "targets": "> 0.5%, last 2 versions, not dead, not ie 11", "useBuiltIns": "usage", "corejs": "3.38", "modules": false } ], [ "@babel/preset-react", { "runtime": "automatic" } ], [ "@babel/preset-typescript", { "allExtensions": true, "isTSX": true } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": false, "helpers": true, "regenerator": true } ] ], "env": { "test": { "presets": [ ["@babel/preset-env", { "targets": { "node": "current" }, "modules": "commonjs" }] ] } } } The parameter "modules": false is critical for bundlers—it allows Webpack or Rollup to handle ECMAScript modules and perform tree-shaking. In the test environment (Jest), "modules": "commonjs" is needed because Node expects CommonJS.
Why separate environments?
The env section lets you override any settings for a specific environment. For example, you can disable minification in development and add plugins to remove console.log in production.Choosing Presets: Table
| Preset | Purpose | When to Include |
|---|---|---|
| @babel/preset-env | Transpile modern JS for target browsers | Always (required) |
| @babel/preset-react | Transform JSX and React syntax | React projects |
| @babel/preset-typescript | Support TypeScript (without type checking) | TypeScript projects |
Targets and browserslist
Instead of hardcoding targets in the Babel config, use .browserslistrc or a browserslist section in package.json—this file is automatically read by Babel, Autoprefixer, and other tools. Example for production:
# .browserslistrc [production] > 0.5% last 2 versions not dead not ie 11 [development] last 1 chrome version last 1 firefox version last 1 safari version Browserslist covers ~95% of active browsers. If you need to support IE 11, add "ie 11", but note that this will increase the polyfill size by 15–20%.
TypeScript Decorators
Decorators (metadata, Angular, MobX, TypeORM) require a special plugin:
npm install --save-dev @babel/plugin-proposal-decorators { "plugins": [ ["@babel/plugin-proposal-decorators", { "version": "2023-11" }] ] } The version "2023-11" is the finalized TC39 Stage 3 standard. For legacy TypeScript decorators (experimentalDecorators: true), use "legacy".
Writing a Custom Plugin
Babel plugins are functions that work with AST. Example: replace all console.log() with noop in production:
// babel-plugin-remove-console.js module.exports = function ({ types: t }) { return { visitor: { CallExpression(path) { const callee = path.get('callee'); if ( callee.isMemberExpression() && callee.get('object').isIdentifier({ name: 'console' }) && callee.get('property').isIdentifier({ name: 'log' }) ) { path.remove(); } }, }, }; }; Attach the plugin via the env section in babel.config.json. A custom plugin can do anything—from replacing API calls to inlining resources. This provides flexibility that SWC cannot match.
Integration with Build Tools
Webpack
Install babel-loader and add a rule to webpack.config.js. Enable caching to speed up repeated builds.
// webpack.config.js module.exports = { module: { rules: [ { test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { cacheDirectory: true, cacheCompression: false, }, }, }, ], }, }; Jest
Jest automatically picks up the Babel config if babel.config.json exists. For a separate config, specify the path in jest.config.js.
// jest.config.js module.exports = { transform: { '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { configFile: './babel.config.test.json' }], }, }; Setup Process and Timelines
Our turnkey Babel setup includes:
- Configuring
babel.config.jsonwith optimized presets for your targets. - Integration with Webpack, Vite, or another bundler.
- Polyfill configuration via core-js (using
useBuiltIns: 'usage'reduces bundle size by 20–30% compared to'entry'). - Documentation for browserslist and environments.
- Support for custom plugins if needed.
- Building and testing across all target browsers.
| Setup Type | Time |
|---|---|
| Basic (React/TypeScript) | 1–2 hours |
| With decorators and polyfills | 4–8 hours |
Cost is calculated individually—depends on project complexity and number of environments. Contact us for a free audit of your current build, and we'll find the optimal configuration.
Speeding Up Builds and Analysis
Babel can be a bottleneck. Use caching (cacheDirectory: true), and for production builds consider switching to SWC. However, if you need non-standard transformations, Babel is unbeatable.
Analyze what is being transpiled using the CLI: npx babel src/index.ts --out-file /dev/stdout --presets @babel/preset-typescript,@babel/preset-env.
Why Trust Professionals with Configuration?
Incorrect Babel configuration leads to duplicated polyfills, increased bundle size, and slower load times. Over the years, we have configured Babel for 50+ projects and guarantee correct operation across all target browsers. Order Babel configuration for your project—and we will provide an optimal setup.







