Fix Unexpected ES2015+ Syntax in Babel Output – Diagnostic Guide
If your Babel bundle still contains arrow functions even though you target modern browsers, this guide walks you through diagnosing the mismatch, checking config files, and applying the right fixes to get pure ES5 output.
19 Apr 2026, 15:09 UTC

Recognizable Condition
After running npx babel src -d lib you still see arrow functions, classes or other ES2015+ syntax in lib/index.js. The project declares a browserslist that should support those features (e.g., "> 0.25%, not dead").
Common Causes
| Cause | Typical Symptom |
|---|---|
| Browserslist query does not match the target environment | Preset‑env reports no transformations for the declared feature |
Missing or mismatched core-js when useBuiltIns is enabled | Polyfills are not injected; runtime errors in older browsers |
| Preset‑env placed before custom plugins that alter the AST | Target resolution is overridden; syntax remains |
| Using an older Babel version that has a bug in target resolution | Unexpected syntax in output, even with correct config |
Diagnostic Checklist
- Verify the
browserslistconfiguration. Open.browserslistrcor thebrowserslistsection inpackage.json. Ensure the query is what you expect (e.g., "> 0.25%, not dead"). - Check the Babel config. In
babel.config.jsconfirm that@babel/preset-envis present and thattargetsorignoreBrowserslistConfig: falseare set correctly. - Run Babel with debug output. Execute:
This prints the resolved targets and the list of plugins that will run. Verify that the targets match thenpx babel src --debug --out-dir libbrowserslistquery. - Inspect the generated file. Open
lib/index.jsand look for arrow functions or classes. If they exist, note the line numbers. - Confirm
useBuiltInsandcore-js. If you setuseBuiltIns: 'usage'or'entry', ensurecore-jsis installed at the same major version as Babel recommends (e.g.,core-js@3for Babel 7.12+).
Fixes Tied to Findings
- Browserslist mismatch. Adjust the query to include the browsers that actually run your code. Example:
Re‑run Babel and confirm that the debug output now lists the correct target browsers.# .browserslistrc > 0.25%, not dead not ie 11 - Missing polyfills. If
useBuiltInsis'usage'or'entry', install the matching core‑js:
Then add an entry point polyfill (fornpm install core-js@3 --save'entry') or verify that Babel injects imports automatically (for'usage'). - Plugin order issue. Ensure
@babel/preset-envis the last preset in the array, so it can apply syntax transforms after any custom presets. Example:module.exports = { presets: [ ['@babel/preset-react', { runtime: 'automatic' }], '@babel/preset-env' ], plugins: [/* custom plugins */] }; - Babel version. Upgrade to the latest stable Babel if you suspect a bug. Run
npm install @babel/core@latest @babel/cli@latest @babel/preset-env@latest.
Escalation Path
If, after applying the above fixes, arrow functions or classes still appear, consider:
- Creating a minimal reproduction with only
src/index.js,babel.config.js, and.browserslistrc. If the minimal build works, the issue lies in other plugins or presets. - Running
npx babel --debugand looking for anyignoreBrowserslistConfig: trueflags that may be set by a plugin. - Checking for
@babel/plugin-transform-modules-commonjsor similar that might reset thetargetsto a default of{ esmodules: true }. - Consulting the Babel issue tracker for known bugs in the specific version you use.
Practical Verification Steps
- Run
npx babel src --debug --out-dir liband capture thetargetssection. It should list browsers likechrome 80,firefox 75, etc. - Open
lib/index.jsand confirm that arrow functions are replaced withfunctionand classes withvar _class = function () { ... }. - Execute the output in a browser that matches the lowest target (e.g., Chrome 80). If no syntax errors appear, the transformation succeeded.
- If you used
useBuiltIns: 'usage', search the output forimport "core-js/modules/..."statements. They should only appear for features actually used.
Key Takeaway
Unexpected ES2015+ syntax in Babel output usually signals a mis‑configured browserslist, missing polyfills, or a plugin ordering issue. By systematically verifying each layer—query, Babel config, debug output, and final bundle—you can pinpoint the root cause and apply the precise fix.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.