Why ReluxScript?
The Problem
Building AST transformation plugins is hard, and maintaining them across multiple platforms is even harder.
The Current Landscape
Babel Plugins (JavaScript)
- ✅ Flexible and easy to write
- ✅ Rich ecosystem
- ❌ Slow (JavaScript runtime)
- ❌ No type safety
- ❌ Large runtime overhead
SWC Plugins (Rust)
- ✅ Fast (native Rust)
- ✅ Type-safe
- ✅ WASM support
- ❌ Complex to write
- ❌ Steep learning curve
- ❌ Smaller ecosystem
The Duplication Problem
- Maintaining both = 2x the code, 2x the bugs, 2x the work
- Features added to one but not the other
- Subtle behavioral differences between implementations
The Solution
ReluxScript lets you write once, compile to both.
// Write this once
plugin RemoveConsole {
fn visit_call_expression(node: &mut CallExpression, ctx: &Context) {
if matches!(node.callee, "console.log") {
*node = Statement::empty();
}
}
}Compiles to both:
dist/index.js- Babel plugin (JavaScript)dist/lib.rs- SWC plugin (Rust)
Key Benefits
1. Write Once, Run Everywhere
Stop maintaining duplicate codebases. Write your plugin logic once in ReluxScript, and it automatically compiles to both Babel and SWC.
2. Type Safety
Catch errors at compile time with static type checking:
// This won't compile - type mismatch
let name: Str = 42; // ERROR: expected Str, found i323. Vector Intersection Principle
We only support features that work identically in both Babel and SWC:
- ✅ What compiles will work correctly on both platforms
- ✅ No surprises or platform-specific bugs
- ✅ Predictable behavior
Better to support 80% of use cases perfectly than 100% with edge case bugs.
4. Performance
Get the best of both worlds:
- Development: Fast iteration with Babel (Node.js)
- Production: Native performance with SWC (Rust/WASM)
5. Familiar Syntax
Rust-inspired syntax that feels natural:
// Clean, expressive code
for arg in &node.arguments {
if let Some(value) = get_string_value(arg) {
println!("Argument: {}", value);
}
}6. Extensible Beyond Babel & SWC
ReluxScript isn't limited to Babel and SWC. The compiler architecture supports custom code generation targets.
Want to compile TypeScript/JSX to C#? Go? Python? Add a new codegen backend!
Who It's For
Plugin Authors
Stop maintaining duplicate codebases. Write once, target both ecosystems.
Before ReluxScript:
- 500 lines of Babel plugin code
- 500 lines of SWC plugin code
- 2x maintenance burden
With ReluxScript:
- 300 lines of ReluxScript
- Auto-generates both targets
- Single source of truth
Tool Builders
Use ReluxScript as your plugin format. Let users write once, deploy everywhere.
Example: Build a bundler that accepts ReluxScript plugins and automatically provides both Babel and SWC compatibility.
Framework Teams
Build custom transpilers from TypeScript/JSX to your target language.
Example: Minimact uses ReluxScript to transpile React/TSX to C# for ASP.NET Core.
Comparison
| Feature | Babel Only | SWC Only | ReluxScript |
|---|---|---|---|
| Language | JavaScript | Rust | ReluxScript |
| Targets | Babel | SWC | Both |
| Type Safety | ❌ | ✅ | ✅ |
| Easy to Write | ✅ | ❌ | ✅ |
| Performance | Slow | Fast | Fast in production |
| Maintenance | 1 codebase | 1 codebase | 1 codebase |
| Cross-platform | ❌ | ❌ | ✅ |
Real-World Use Case
Minimact Plugin
The Minimact plugin (123 files, ~15K lines) was originally written in JavaScript as a Babel plugin. Converting to ReluxScript provides:
- Dual compilation - Works with both Babel and SWC toolchains
- Type safety - Catches errors before runtime
- Better performance - SWC version runs natively
- Single codebase - One implementation, two outputs
Design Principles
1. Correctness Over Coverage
We choose to support a smaller feature set perfectly rather than a larger feature set with edge cases.
If a feature can't work identically on both platforms, we don't include it.
2. Explicit Over Implicit
All mutations must be explicit:
*node = Statement::empty(); // Clear: replacing node
node.name.clone() // Clear: copying valueNo magic, no surprises.
3. Performance Through Options
Choose your performance profile:
- Development: Use Babel output for fast iteration
- Production: Use SWC output for maximum performance
- Both: Test in Babel, ship with SWC
Getting Started
Ready to try ReluxScript?
Philosophy
"The best code is code you only have to write once."
ReluxScript embodies this philosophy. Write your AST transformation logic once, in a clean, type-safe language, and let the compiler handle the complexity of generating platform-specific code.
