How @babel/preset-env Works
Core Concept
@babel/preset-env is a smart preset that automatically determines the Babel plugins and polyfills needed based on your target environment (browser or Node.js versions), without manually configuring each transformation.
Working Mechanism
javascript// babel.config.js module.exports = { presets: [ ['@babel/preset-env', { targets: { browsers: ['> 1%', 'last 2 versions', 'not dead'], node: 'current' }, useBuiltIns: 'usage', corejs: 3 }] ] };
Workflow:
- Target Environment Analysis: Parse
targetsconfiguration - Plugin Selection: Determine required syntax transformation plugins based on target support
- Polyfill Processing: Handle polyfills according to
useBuiltInsconfiguration - Code Transformation: Apply selected plugins for transformation
useBuiltIns Options Explained
1. false (default)
Does not automatically add polyfills, requires manual import.
javascript// babel.config.js { useBuiltIns: false } // Manual import in entry file import 'core-js/stable'; import 'regenerator-runtime/runtime';
Characteristics:
- Full manual control of polyfills
- May introduce unnecessary polyfills
- Package size may be large
2. "entry"
Replaces import 'core-js' with specific required polyfills based on target environment.
javascript// babel.config.js { useBuiltIns: 'entry', corejs: 3 } // Source code import 'core-js/stable'; // After transformation (assuming target environment needs) import 'core-js/modules/es.array.iterator'; import 'core-js/modules/es.promise'; // ... other required polyfills
Characteristics:
- Replaces core-js imports in entry files
- Filters unnecessary polyfills based on target environment
- Global pollution (modifies native prototypes)
3. "usage"
Introduces polyfills on-demand based on actual features used in code.
javascript// babel.config.js { useBuiltIns: 'usage', corejs: 3 } // Source code const arr = [1, 2, 3]; arr.includes(2); const promise = Promise.resolve(1); // After transformation import 'core-js/modules/es.array.includes'; import 'core-js/modules/es.promise'; var arr = [1, 2, 3]; arr.includes(2); var promise = Promise.resolve(1);
Characteristics:
- On-demand import, minimizes polyfill size
- No manual core-js import needed
- Global pollution (modifies native prototypes)
- Recommended for application development
Comparison Summary
| Option | Import Method | Package Size | Global Pollution | Use Case |
|---|---|---|---|---|
| false | Manual | Largest | Yes | Library dev (not recommended) |
| entry | Entry file replacement | Medium | Yes | Applications |
| usage | Automatic on-demand | Smallest | Yes | Applications (recommended) |
Difference from @babel/plugin-transform-runtime
useBuiltIns: 'usage' + core-js
javascript// Global pollution approach Array.prototype.includes = ... // Modifies global prototype
@babel/plugin-transform-runtime + core-js
javascript// babel.config.js { plugins: [ ['@babel/plugin-transform-runtime', { corejs: 3 // Uses modular version of core-js }] ] }
Characteristics:
- Does not pollute global environment
- Suitable for library/tool development
- Uses sandboxed polyfills
javascript// Before transformation const arr = [1, 2, 3]; arr.includes(2); // After transformation (no global pollution) import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes"; var arr = [1, 2, 3]; _includesInstanceProperty(arr).call(arr, 2);
Best Practices
1. Application Development
javascript// babel.config.js module.exports = { presets: [ ['@babel/preset-env', { targets: { browsers: ['> 1%', 'last 2 versions'] }, useBuiltIns: 'usage', corejs: 3 }] ] };
2. Library/Tool Development
javascript// babel.config.js module.exports = { presets: ['@babel/preset-env'], plugins: [ ['@babel/plugin-transform-runtime', { corejs: 3, helpers: true, regenerator: true }] ] };
3. Configure browserslist
json// package.json { "browserslist": [ "> 1%", "last 2 versions", "not dead" ] }
Debugging Tips
bash# View actual plugins and polyfills used DEBUG=* npx babel src/index.js # View only preset-env information DEBUG=@babel/preset-env npx babel src/index.js