ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 06

  1. Blog

oxc-parser vs @babel/parser: 9.1 ms vs 47.9 ms on 513 KB

Aditya Challa·5 October 2026·8 min read

Hands-on
On this page
  1. What I tested
  2. Is oxc-parser 5x faster than Babel?
  3. What happens on Node 20?
  4. Which one starts faster?
  5. What does each one cost to install and bundle?
  6. Do they behave the same?
  7. Which one should you pick?
  8. Sources
  9. Related

I timed oxc-parser 0.153.0 against @babel/parser 7.29.9 on a 513 KB JavaScript file on this box: 9.1 ms vs 47.9 ms per parse on Node 22 with oxc's experimentalRawTransfer option (4.3× to 5.3× across two runs). With oxc's default JSON path the same file took 62.6 ms vs Babel's 47.9 ms, so the "5x faster" claim only held when raw transfer was on.

Short answer: pick oxc-parser when you are on Node 22+ and can turn on raw transfer, or when you only need the import/export record. Stay on @babel/parser when you are on Node 20, depend on Babel's AST shape (File, StringLiteral, loc), or already run Babel plugins. No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 04:00 IST.
  • Versions: oxc-parser 0.153.0 and @babel/parser 7.29.9 (both npm latest that day), Node 20.19.2 and Node 22.14.0, esbuild 0.28.2 for bundle sizes.
  • Workload: four fixtures. A 240 B ESM file, a 15,414 B TypeScript file (trace-mapping.ts), an 18,316 B TSX file (a TanStack Router route.tsx), and a 513,377 B CommonJS-style build (Babel's own lib/index.js). oxc ran parseSync and I read result.program so the AST was actually built. Babel ran parse with sourceType module and the typescript / jsx plugins where the file needed them.
  • Timing: median of 9 rounds (5,000 / 500 / 500 / 12 iterations by size), two processes per Node version with the run order flipped. Scripts and JSON in /workspace/bench-oxc-babel-parser/.
  • Also measured: cold import plus first parse (11 fresh processes), esbuild bundle size, install size, error handling on a broken file, AST shape, and node counts.
  • Not tested: oxc's async parse() on worker threads, experimentalLazy, the Visitor API, Babel's estree plugin, @babel/traverse or transforms, Bun and Deno, Windows or macOS bindings.

Is oxc-parser 5x faster than Babel?

Node 22.14.0, median ms per parse (run 1 / run 2):

Fixtureoxc raw transferoxc defaultoxc module record only@babel/parser
small.mjs, 240 B0.0155 / 0.01040.0443 / 0.02670.0603 / 0.03230.0205 / 0.0113
medium.ts, 15,414 B0.264 / 0.2562.447 / 1.4570.598 / 0.4920.812 / 1.038
route.tsx, 18,316 B0.353 / 0.2381.497 / 1.4760.583 / 0.5881.077 / 1.284
large.js, 513,377 B9.06 / 9.5762.55 / 60.2312.20 / 12.1747.89 / 41.58

With raw transfer, oxc beat Babel by 3.1× to 4.1× on the TypeScript file, 3.1× to 5.4× on the TSX file, and 4.3× to 5.3× on the large file. Without it, oxc was slower than Babel on every fixture, because the default path serializes the AST to JSON in Rust and then runs JSON.parse in JavaScript. Raw transfer skips that step, and its AST JSON matched the default output on all four fixtures. If you are already comparing Rust-backed compilers, my swc vs esbuild vs Babel run covers the transform side; this post is only about parsing. If you only need export names from plain ESM, the lighter acorn-based route is in mlly vs acorn.

What happens on Node 20?

Node 20.19.2, median ms per parse (run 1 / run 2). Raw transfer is not available here; the option threw "not supported on ... versions of NodeJS prior to v22.0.0".

Fixtureoxc defaultoxc module record only@babel/parser
small.mjs, 240 B0.0650 / 0.05270.0526 / 0.06200.0121 / 0.0208
medium.ts, 15,414 B1.790 / 1.8421.010 / 1.3521.110 / 1.109
route.tsx, 18,316 B1.866 / 1.8851.039 / 0.8501.231 / 1.322
large.js, 513,377 B70.65 / 58.4315.40 / 12.2445.20 / 44.33

On Node 20, oxc's full AST was 1.3× to 1.6× slower than Babel on the large file. Reading only result.module (static imports and exports) without touching result.program came out ahead on the bigger files: about 12 to 15 ms vs 44 to 45 ms on large.js and 0.85 to 1.04 ms vs 1.23 to 1.32 ms on route.tsx. On the 15 KB TypeScript file it was mixed, and on the 240 B file Babel still won. If your CI still pins Node 20, moving to 22 is the bigger win; I compared version managers in Volta vs fnm.

Which one starts faster?

Cold import + first parse (median of 11 processes)oxc-parser@babel/parser
Node 20.19.219.69 ms57.41 ms
Node 22.14.011.59 ms49.47 ms

oxc loaded about 3× to 4× faster in a fresh process. That matters for short-lived CLIs and lint hooks, the same reason oxlint vs ESLint and Biome vs ESLint + Prettier show such large wall-clock gaps on small repos.

What does each one cost to install and bundle?

Packageesbuild minifiedgzip -9Install (fresh npm i)
@babel/parser 7.29.9308,323 B78,863 B5,412 KB, 4 packages
oxc-parser 0.153.0, JS wrapper24,445 B4,567 B7,136 KB, 4 packages
oxc native binding (linux-x64-gnu .node)2,104,992 B876,249 Bincluded above

oxc's JavaScript is small, but it loads a 2.1 MB native addon at runtime that esbuild cannot inline, so treat it as an external dependency when you bundle a CLI. npm on this box also pulled the musl binding next to the glibc one, which is part of the 7,136 KB. If you track package weight in CI, the setup in size-limit vs bundlesize works for both.

Do they behave the same?

Checkoxc-parser 0.153.0@babel/parser 7.29.9
Broken file (missing paren, dangling +)no throw; 1 error in result.errors, empty bodythrew BABEL_PARSER_SYNTAX_ERROR
Same file with errorRecovery: truen/astill threw
.ts file with no extra options0 errors; language picked from the file extensionthrew unless plugins: ['typescript']
Root nodeProgram (ESTree)File wrapping Program
String literal nodeLiteralStringLiteral
Location infostart / end offsets, no locstart / end plus loc lines and columns
Nodes in route.tsx / large.js2,317 / 76,2742,219 / 75,081
Imports / exports in route.tsx19 / 17 via result.module19 ImportDeclaration / 17 Export nodes
Comments in route.tsx1515

The AST shapes are not interchangeable. Code written against Babel node types (StringLiteral, File, loc) will need changes to read oxc's ESTree output, and the reverse is also true. Tools that already speak ESTree, such as bundlers in the Rolldown vs Rollup family, fit oxc's output more naturally.

Which one should you pick?

SituationMy pick
Node 22+, you need the full AST fastoxc-parser with experimentalRawTransfer
Node 20 and you need the full AST@babel/parser
You only need imports and exportsoxc-parser, read result.module
You run Babel plugins or @babel/traverse@babel/parser
Short-lived CLI where startup dominatesoxc-parser (11.6 vs 49.5 ms cold on Node 22)
You need errors returned, not thrownoxc-parser
You bundle the parser into a single JS file@babel/parser (no native addon)

Bottom line: on this box oxc-parser 0.153.0 parsed a 513 KB file in about 9 ms vs Babel's 42 to 48 ms, but only on Node 22 with raw transfer on. On its default path, or on Node 20, Babel was faster for full ASTs. Who should not switch yet: teams on Node 20, anyone who depends on Babel's node types, and anyone shipping a single-file bundle. Who should try oxc now: Node 22 tool authors who parse many files and can handle ESTree. For the loader side of a TypeScript toolchain, see tsx vs ts-node.

How this was made: I installed both parsers on the ShopperCove box, timed four fixtures over 9 rounds in two processes per Node version (20.19.2 and 22.14.0), checked cold start in 11 fresh processes, bundled each entry with esbuild, ran a fresh npm install for size, and compared error handling and AST output. The JSON results sit next to the scripts. The write-up was drafted with AI help and checked against that output.

Sources

  • https://github.com/oxc-project/oxc/tree/main/napi/parser
  • https://oxc.rs/docs/guide/usage/parser.html
  • https://www.npmjs.com/package/oxc-parser
  • https://babeljs.io/docs/babel-parser
  • https://www.npmjs.com/package/@babel/parser
  • https://github.com/babel/babel/tree/main/packages/babel-parser

Related

  • https://www.shoppercove.com/blog/swc-vs-esbuild-babel
  • https://www.shoppercove.com/blog/oxlint-vs-eslint
  • https://www.shoppercove.com/blog/biome-vs-eslint-prettier
  • https://www.shoppercove.com/blog/rolldown-vs-rollup
  • https://www.shoppercove.com/blog/volta-vs-fnm
  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/tsx-vs-ts-node
  • https://www.shoppercove.com/blog/mlly-vs-acorn
oxc-parserbabeljavascripttypescriptparsingperformancenode.js

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~04:00 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2 and 22.14.0). oxc-parser 0.153.0 vs @babel/parser 7.29.9; esbuild 0.28.2. Fixtures 240 B mjs / 15,414 B ts / 18,316 B tsx / 513,377 B js. Median of 9 rounds x 5,000/500/500/12, 2 processes each Node. Node 22 raw transfer: 0.0155/0.0104, 0.264/0.256, 0.353/0.238, 9.06/9.57 vs Babel 0.0205/0.0113, 0.812/1.038, 1.077/1.284, 47.89/41.58. Default oxc slower than Babel on every fixture (large 62.55/60.23 Node 22; 70.65/58.43 vs 45.20/44.33 Node 20). Module-record-only large 12.2 ms. Raw AST JSON identical to default on all 4. Cold 19.69 vs 57.41 ms (N20), 11.59 vs 49.47 (N22). Behavior: oxc returned 1 error on broken file, Babel threw (errorRecovery too); Babel needs typescript plugin; ESTree Literal vs StringLiteral/File/loc. Not tested: async parse, lazy, Visitor, Bun/Deno. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 38

    smol-toml vs @iarna/toml: 3x Faster on Deno Cargo

    5 Oct 2026

  • Plate 85

    consola vs pino: 155k vs 371k Log Lines/s on Node 20

    5 Oct 2026

  • Plate 08

    fast-glob vs globby: 0.7 ms vs 14 ms With gitignore

    5 Oct 2026

On this page

  1. What I tested
  2. Is oxc-parser 5x faster than Babel?
  3. What happens on Node 20?
  4. Which one starts faster?
  5. What does each one cost to install and bundle?
  6. Do they behave the same?
  7. Which one should you pick?
  8. Sources
  9. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove