You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
magicast is a fantastic tool that heavily relies on recast to achieve its "superpower": non-destructive AST modification (parsing and generating code while perfectly preserving the original formatting, spaces, and comments).
While recast has been the industry standard for this task for years, the JavaScript ecosystem is rapidly moving towards faster, leaner, and more modern toolchains.
🚨 The Problem with recast
Currently, relying on recast introduces a few pain points that clash with the general UnJS philosophy (which usually aims for minimal, ultra-fast, and lightweight tools):
Bundle Size & Weight:recast brings in legacy dependencies (like ast-types) and often requires heavyweight parsers (like Babel) under the hood.
Performance: Compared to modern Rust/Go-based parsers, recast is relatively slow.
Maintenance & Modern Syntax: Keeping up with the latest TypeScript or ECMAScript features sometimes causes friction or requires waiting for upstream updates in multiple parsers.
Unmaintained: Last commit date (3 Mar 2025) ~ Last release date (3 Mar 2025)
Issues: e.g. tabs, indentation
🔍 Potential Alternatives
I understand that there is currently no true 1:1 drop-in replacement forrecast based on the ESTree standard that guarantees non-destructive printing. However, looking towards a potential v2 or future architecture, I would like to propose a discussion around these modern alternatives:
ast-grep (via @ast-grep/napi) 🦀
This seems to be the most viable and modern replacement for codemods today. Pros: Written in Rust, based on Tree-sitter. Instead of a traditional AST, it uses a CST (Concrete Syntax Tree), which natively maps spaces, punctuation, and comments. It is incredibly fast and preserves formatting by design. Cons: It does not use the ESTree standard. Migrating to ast-grep would mean dropping the current Proxy-based AST logic and rewriting the core engine to interact with ast-grep's APIs. A major paradigm shift.
Monitoring Oxc (Oxidation Compiler) or Biome 🦀 Pros: Blazing fast AST parsing and growing ecosystems. Cons: As of right now, they lack mature, exposed APIs for non-destructive printing in Node.js. However, since the UnJS ecosystem is already embracing tools like Rolldown / Oxc, it might be worth opening a dialogue with the Oxc team to see if a non-destructive printer is on their roadmap.
ts-morph (Mentioned just for completeness)
While it's excellent at preserving formatting using the official TypeScript compiler API, it is likely way too heavy and slow for a lightweight CLI tool, going against the UnJS ethos. I mention it only to rule it out.
🛠️ Architectural Impact
Replacing recast would not be a simple PR; it would require a complete rewrite of the magicast core, since the library's elegant Proxy implementation is tightly coupled with how recast and ESTree handle nodes.
Has the team already considered moving away from recast?
Is the current performance/size of recast considered a bottleneck for the future of magicast?
Would an experimental PR (or a separate branch) exploring a CST-based approach (like ast-grep) be welcome, or is the ESTree compatibility a strict requirement for this project?
I would love to hear your thoughts on this and see if there is room for the community to help modernize the core engine.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
💡 Context
magicastis a fantastic tool that heavily relies onrecastto achieve its "superpower": non-destructive AST modification (parsing and generating code while perfectly preserving the original formatting, spaces, and comments).While
recasthas been the industry standard for this task for years, the JavaScript ecosystem is rapidly moving towards faster, leaner, and more modern toolchains.🚨 The Problem with
recastCurrently, relying on
recastintroduces a few pain points that clash with the general UnJS philosophy (which usually aims for minimal, ultra-fast, and lightweight tools):recastbrings in legacy dependencies (likeast-types) and often requires heavyweight parsers (like Babel) under the hood.recastis relatively slow.🔍 Potential Alternatives
I understand that there is currently no true 1:1 drop-in replacement for
recastbased on the ESTree standard that guarantees non-destructive printing. However, looking towards a potential v2 or future architecture, I would like to propose a discussion around these modern alternatives:ast-grep(via@ast-grep/napi) 🦀This seems to be the most viable and modern replacement for codemods today.
Pros: Written in Rust, based on Tree-sitter. Instead of a traditional AST, it uses a CST (Concrete Syntax Tree), which natively maps spaces, punctuation, and comments. It is incredibly fast and preserves formatting by design.
Cons: It does not use the ESTree standard. Migrating to
ast-grepwould mean dropping the current Proxy-based AST logic and rewriting the core engine to interact withast-grep's APIs. A major paradigm shift.Monitoring
Oxc(Oxidation Compiler) orBiome🦀Pros: Blazing fast AST parsing and growing ecosystems.
Cons: As of right now, they lack mature, exposed APIs for non-destructive printing in Node.js. However, since the UnJS ecosystem is already embracing tools like
Rolldown/Oxc, it might be worth opening a dialogue with the Oxc team to see if a non-destructive printer is on their roadmap.Related Feature Requests:
ast-grep/jscodeshift) oxc-project/oxc#22055ts-morph(Mentioned just for completeness)While it's excellent at preserving formatting using the official TypeScript compiler API, it is likely way too heavy and slow for a lightweight CLI tool, going against the UnJS ethos. I mention it only to rule it out.
🛠️ Architectural Impact
Replacing
recastwould not be a simple PR; it would require a complete rewrite of themagicastcore, since the library's elegant Proxy implementation is tightly coupled with howrecastand ESTree handle nodes.💬 Questions for the Maintainers (@antfu, @pi0)
recast?recastconsidered a bottleneck for the future ofmagicast?ast-grep) be welcome, or is the ESTree compatibility a strict requirement for this project?I would love to hear your thoughts on this and see if there is room for the community to help modernize the core engine.
Disclaimer
Content improved using AI to wrap-up concepts
Beta Was this translation helpful? Give feedback.
All reactions