WARNING
The Oxc Angular Compiler is an experiment for research purposes.
VoidZero built an Angular Compiler on the VoidZero stack using AI that has up to 20x faster code compiling speed. It transforms templates at Rust speed and can be used as either a first class Vite plugin or programmatic API.
Building something as complex as the Angular Compiler under these conditions would have been inconceivable previously. The Angular team did an amazing job building it. But AI coding agents changed that. Under the guidance of experienced engineers, agents can complete large scale projects.
We wanted to see how far we can get. To see how fast our tooling can be accelerate experimentation.
And we have skin in the game. We want more developers using Vite. Vite has become the default build tool for the modern web with >60M weekly downloads at the time of writing. The latest versions of Angular CLI are already using Vite for the dev server. But not for production builds.
This blog post is split into 2 parts:
Introducing Oxc Angular Compiler Experiment
The Oxc Angular Compiler was created after 2 months of collaborative development with Claude Code and Codex that:
- Is a first-class Vite plugin with full HMR support
- Is built on VoidZero’s Oxc, the same Rust-based language tool that powers Vite 8 onwards.
- Fully supports Angular’s primitives.
DANGER
It does not implement Angular's cross-file optimizations or support template type-checking.
Faster code compiling speed
The Vite 8 + Oxc Angular Compiler was able to compile code faster.
- 6.4x faster than Angular CLI on Super Productivity
- 20.7x faster than Webpack +
@ngtools/webpackon Bitwarden
The performance difference is driven by the differing approaches each compiler takes. While using Rust did contribute to the performance improvement, a bigger reason is the differing approaches of each compiler.
Angular’s existing compiler compiles HTML templates into TypeScript code and then runs TypeScript Compiler to generate the JavaScript output. While generating the JavaScript output, Angular compiler uses TypeScript Compiler’s semantic information for optimizations. Therefore, Angular compiler is unable to skip the type check, which otherwise accelerates build. Meaning it effectively performs deep, whole-program type analysis on template-generated TypeScript code. This becomes exponentially more expensive as applications grow.
Rather than driving template compilation through TypeScript’s checker, Oxc Angular Compiler implements the template compiler and the required analysis natively in Rust using Oxc and integrates it into Vite through NAPI-RS. This reduces how much the build depends on TypeScript’s semantic checker. Resulting in less overhead and much faster compiling.
Getting started
Oxc Angular can be used as either (1) a first-class vite plugin or (2) a programmatic API.
npm install @oxc-angular/vite
# or
pnpm add @oxc-angular/vite
# or
yarn add @oxc-angular/viteFirst-class Vite Plugin
// vite.config.ts
import { defineConfig } from 'vite'
import { angular } from '@oxc-angular/vite'
export default defineConfig({
plugins: [
angular({
// Optional configuration
angularVersion: 21,
enableHmr: true,
}),
],
})Programmatic API
import { compileTemplate, transformAngularFile } from '@oxc-angular/vite/api'
// Compile a template string
const result = await compileTemplate(
'<div>{{ message }}</div>',
'AppComponent',
'app.component.ts',
{
angularVersion: 21,
enableHmr: false,
},
)
console.log(result.code)
// Transform an entire Angular file
const transformed = await transformAngularFile(
`
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<h1>Hello {{ name }}</h1>',
})
export class AppComponent {
name = 'World';
}
`,
'app.component.ts',
)
console.log(transformed.code)For more details: https://github.com/voidzero-dev/oxc-angular-compiler
What’s Next
As previously mentioned, the Oxc Angular Compiler is an experiment to test what’s possible with AI and showcase Oxc’s speed. The project will not be maintained. It’s a reference on how to implement Angular’s single-file compilation completely in Rust.
In parallel, the Angular team have been conducting their own experiments with Oxc. Specifically, for the TypeScript parsing while feeding Angular’s existing template compiler because it enables more incremental porting. There’s a potential future where the Oxc Angular Compiler is integrated into Angular’s official full compiler stack.
How I collaborated with coding agents
Written by Brooklyn, creator of the Oxc Angular Compiler
Testing System
When working with a Coding Agent on a porting project of this scale, the most critical part of achieving results consistent with the original project is designing a comprehensive testing system.
Fortunately, https://github.com/oxc-project/oxc had already implemented many similar tests: test262, and consistency tests for Babel/TypeScript/ESLint/Prettier. When I first started developing the Oxc Angular Compiler with Claude Code, it didn’t yet support the skills feature. In fact, when developing within the Oxc repository, such skills files weren’t necessary because the existing code itself functioned as skills. I found that the Coding Agent naturally followed the Oxc project’s conventions to set up the testing framework. Within the first few hours of development, Claude Code had already established a complete unit tests / snapshot tests / conformance testing workflow for the project. It wasn’t until development was about 90% complete that I migrated the full Oxc Angular Compiler code out of the Oxc repository into a standalone project.
Start with Plan Mode
I began with Plan mode. During the initial planning process, Claude Code thoroughly analyzed the entire Oxc project and identified several key points:
- How to set up a complete testing pipeline to reuse
AngularTypeScript compiler tests Oxcalready has components like Parser/Semantic/Transformer, which can replace the corresponding functionality in TypeScript- How to write high-performance Rust code like
Oxcdoes—using arena to reduce memory allocations and leveraging various existing SIMD crates to improve performance
This knowledge was crucial for our project. We not only needed to implement the functionality of the Angular TypeScript compiler but also ensure it was high-performance and maintainable.
After several planning iterations and rounds of collaboration with Claude Code, I found an effective way to let Claude Code run autonomously for longer periods. Here is my prompt:
Let's continue our plan: ~/.claude/plans/peppy-zooming-nygaard.md
Remember, you are the orchestrator, the only job for you is dispatch tasks to subagents and review their works.
You can always finish your TODOs in this way: dispatch a task to a discover subagent let it to collect the info about root cause/how to fix it. And dispatch the output of the discover agent to a new fixer agent to help you fixing it. With the full output of the discover subagent and full context of the issue.
There are some info you always need to pass to your subagents, both discover and fixer:
- Our full plan: ~/.claude/plans/peppy-zooming-nygaard.md
- The angular sources are available at: ./crates/oxc_angular_compiler/angular
There are some requirements you need always tell your discover agent:
- Write down what you find, give back the file path
There are some requirements you need always tell your fixer agent:
- The file path saved by the discover agent
- We are on a fresh new branch, **so never considering the backward compatible, and don't worry about cleanup old/updated impl/tests/comments**.
- Do not leave `_xx = a` or `let _ = xxx` in our impl, we should make it clean, **never use `#[allow(dead_code)]`**
- Never tried to modify the test logics to make it pass, we need strictly 1:1 port.
- Don't use `unwrap` or `expect` in parser/transformer, we need handle the error correctly
- Always compare the control flow with the Angular TypeScript compiler at ./crates/oxc_angular_compiler/angular instead of addressing issues without understanding them. **If you want to make the comparison, use the subagent if possible, as the implementation is quite complex and it is easy to out of context.**
Our ultimate goal is make compare tests all pass! And you need to keep this loop running until no new issues can be found. **Even after context compact, you need still keep in mind what I told you here!**This prompt allowed Claude Code to run autonomously for 4–6 hours (Claude Code version from December 2025). After Claude Code claimed that a task was completed, I didn’t spend too much time polishing the results because the project was very large. In the early stages, there were always more new components and features to develop. So I would typically start a new Plan, have it carefully research our existing implementation and the original Angular TypeScript compiler, then produce a new polishing plan. Once we had a new plan, we could repeat the above prompt and begin a new automated loop.
Detailed Alignment
After about two weeks of development, the project gradually converged. New plans could only identify a small number of issues, and our prompt could only keep it running automatically for about 20 minutes to an hour.
At this stage, I switched to a different development approach: I asked Claude Code to create a plan to fix all tests. In the earlier development process, I intentionally did not enforce a strict requirement that all tests must pass. Otherwise, Claude Code might prematurely get stuck in details before the architecture was complete, making incorrect decisions—using local workarounds to pass tests instead of preserving architectural integrity.
At this stage, my prompt had Claude Code run Compare testing. This test compares the outputs of Ng CLI and the Oxc Angular Compiler in real projects. I spent about a week planning and coding to build this complex testing tool and enabled Claude Code to use the generated report.json to fix test cases one by one.
After about four weeks of fixes, the Oxc Angular Compiler was able to compile projects like Bitwarden into code that was fully semantically equivalent to Angular CLI.
Architecture Alignment
We now had a fairly usable Oxc Angular Compiler, but that didn’t mean it was production-ready. We had passed many e2e tests, but those didn’t cover every compiler scenario—there were always features we hadn’t tested yet.
At this point, I started using Codex for systematic review. Codex is very different from Claude Code. It excels at reviewing large projects because it has built-in context compression techniques, and GPT models typically spend more time reasoning than Claude Opus, allowing them to uncover more detailed issues.
I also found that Codex doesn’t require very detailed prompts. My typical prompt looked like this:
Deep review this repo, compare our implementation with the angular submodule sources.
Compare the control flow and see if there are anything we are un-aligned with the original Angular TypeScript compilerIt consistently identified many subtle issues not covered by tests, for example:
- **Findings**
1. **High Severity:**
`@for` track method-call optimization no longer enforces Angular’s root-view guard.
- **Files & Locations:**
- Rust: `track_fn_optimization.rs:382`, `track_fn_optimization.rs:414`
- TypeScript: `track_fn_optimization.ts:84`, `track_fn_optimization.ts:96`
- **Details:**
In the current Rust implementation, `root_xref` (`_root_xref`) is not checked; it allows any Context receiver to be used for the optimization. In contrast, Angular’s TS requires `receiver.view === rootView`. Without this guard, non-root track calls follow an optimized path (such as `ctx.method` or `componentInstance().method`), whereas the TS version retains wrapper-based behavior.
2. **Medium Severity:**
`@switch` ingest order is intentionally changed—default is moved last, unlike Angular’s original source flow.
- **Files & Locations:**
- Rust: `ingest.rs:2925`, `ingest.rs:2936`
- TypeScript: `ingest.ts:581`
- **Details:**
Angular iterates `switchBlock.groups` based on their source order. The Rust version reorders them to place `@default` last, ahead of view/xref allocation. This can affect alignment in control-flow construction with respect to xref/slot/function ordering and may cause divergence from TS pipeline internals, even if the final output matches.
3. **Medium Severity:**
Divergence in control-flow variable naming compared to Angular remains documented and reproducible.
- **Files & Locations:**
- Rust tests: `variable_naming_test.rs:327`, `variable_naming_test.rs:398`, `variable_naming_test.rs:423`
- **Details:**
The repository documents that nested `ngFor`/`ngIf`/`ngSwitch` control-flow graphs (e.g., `ctx_r2` vs Angular’s `ctx_r4`, `i_r5` vs `i_r6`) have different naming suffixes. This divergence is currently considered semantically acceptable but still represents a misalignment in generated output compared to Angular TS.
- The following tests were specifically checked and passed:
- `switch_block_default_first`
- `for_track_bare_method_reference`
- `variable_naming_divergence_in_nested_ngfor_ngif`
These are alignment issues, not currently causing any immediate test regressions.I would then feed these review results back to Claude Code:
Review comments:
~~~
[Pasted text #1 +24 lines] // from Codex Review
~~~
Use your subagents to verify if they are reasonable. If they are valid, fix them. Add test cases to reproduce before your fixing.
Do it in sequence. And make sure:
- `cargo test`
- `cargo run -p oxc_angular_conformance`
- `pnpm --filter @oxc/angular-compare compare --preset bitwarden --full-file --ng-baseline ./ng-baseline-bitwarden.json`
- `pnpm --filter @oxc/angular-compare compare --fixtures`
All have no regressions!Claude Code would quickly fix these issues and add the necessary test cases to prevent regressions.
After about three weeks of this cycle—until even Codex could no longer find serious issues—we open-sourced the project.
Conclusion
Coding Agents have changed how I develop projects. They allow me to focus more on architectural design. The existing code in the Oxc project guides the Coding Agent in writing similar Rust code. For areas like compiler/transformer development, this practical guidance is more effective than any Skills/Subagents mechanism. It’s very inspiring.
The Oxc Angular Compiler is not a toy project. I carefully designed all testing workflows to ensure it runs well in large-scale projects, including HMR and production builds. I sincerely hope this project can help the Angular community and make it easier for Angular users to migrate to Vite.
Acknowledgements
Thank you to the Angular team for their continued dedication to the Angular framework. Their relentless efforts to building a top-notch framework, comprehensive documentation, and well-crafted test made it possible to create Oxc Angular Compiler.
Thank you to the Clickup team for their interest in the VoidZero stack. They were looking to push the boundaries of what their Angular application could do and reached out to us.
Thank you to the Bitwarden team for open-sourcing their codebase. We were only confident enough to share the Oxc Angular Compiler because we saw it produce the correct results for Bitwarden’s Angular application.




