VuReact is a maintainability-first compilation workflow: you write Vue, and it generates pure React output that a team can actually keep living with.
A first look at VuReact: it is a compile-time workflow for writing Vue and shipping maintainable React, and this walkthrough uses one quickstart path plus one real component migration example to test whether that promise actually holds up.
What Is VuReact?
VuReact is a Vue-to-React compiler toolchain built around a simple idea: keep Vue as the authoring experience, but make React the final artifact.
You write Vue 3 SFCs, VuReact analyzes the template, script, styles, and reactive dependencies, and it generates a React workspace under .vureact/react-app. That output is meant to be read, run, and maintained like a normal React project.
This is why VuReact is easier to reason about than many migration tools at first glance. It is not trying to hide a second runtime. It is trying to give Vue-minded developers a controlled way to land in the React ecosystem.
The Problem That Keeps Coming Back
The expensive part of switching from Vue to React is rarely the first rewrite. It's all the manual maintenance work that keeps coming back afterward.
If you already think in Vue, JSX is usually not the hard part. The hard part is everything around it: useCallback, useMemo, dependency arrays, event naming, and the constant fear that a harmless refactor will quietly break a closure or destabilize a component.
That is the part I wanted to test with VuReact. Not "can it produce React code at all?", but "does it remove a meaningful chunk of React maintenance work without leaving me with a runtime bridge or a hard-to-read output?"
What VuReact Is Not
That gives it a very different goal from many "migration helpers" people usually imagine:
- It is not a runtime bridge.
- It is not a black-box codemod that promises to convert every Vue pattern with zero conventions.
- It is a convention-driven compiler that tries to preserve semantics, keep the output predictable, and make gradual migration possible.
The shortest way I can describe its value is this: VuReact is less about "saving keystrokes" and more about reducing the number of React-specific maintenance decisions you need to keep revisiting by hand.
The 30-Second Try
If you want to get a feel for it before reading further, these are the two fastest entry points:
- Try the Customer Support Hub playground: https://codesandbox.io/p/github/vureact-js/example-customer-support-hub/master?import=true
- Read the quick start: https://vureact.top/guide/quick-start.html
That combination gives you the two things a first article should prove quickly: there is a real workflow, and there is a real output.
The Fastest Happy Path
The quickest VuReact workflow is intentionally small. You do not need to learn the entire project model up front. The core README already frames the happy path well: install the compiler in a Vue 3 project, create vureact.config.ts, and then either test a single SFC first or point the compiler at src.
Install the compiler package:
npm install -D @vureact/compiler-core
Create vureact.config.ts in your project root:
import { defineConfig } from '@vureact/compiler-core';
export default defineConfig({
input: './src',
exclude: ['src/main.ts'],
output: {
workspace: '.vureact',
outDir: 'react-app',
bootstrapVite: true,
},
});
If you want the safest first run, start with one component:
export default defineConfig({
input: './src/your-component.vue',
exclude: ['src/main.ts'],
});
If you want to compile the project structure more broadly, point input at ./src. This is the main quickstart path for a normal Vue app, and the exclude keeps Vue's entry mounting logic out of the compile target.
If your project uses Vue Router, add the router config before compiling.
Then run the compiler once:
npx vureact build
If that succeeds, switch to watch mode:
npx vureact watch
And start the generated React app:
cd .vureact/react-app
npm install
npm run dev
At that point, you should have a generated React project under .vureact/react-app, including converted source files inside its src directory.
That is the happy path VuReact is optimized around:
- Keep writing Vue.
- Let the compiler keep producing React output.
- Validate the generated React project like a normal React app.
This matters because the workflow is not "rewrite everything and pray." It is "establish a stable loop first, then widen the migration scope."
One Real Component Migration
The most useful test is not a benchmark and not a marketing checklist. It is a component that looks close enough to real application code: props, emits, refs, computed state, a couple of callbacks, and scoped styling.
Here is the Vue input, abridged from the same kind of example used in VuReact's existing docs and long-form writeups:
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
const props = defineProps<{ title?: string }>();
const emits = defineEmits<{ (e: 'update', value: number): void }>();
const step = ref(1);
const count = ref(0);
const title = computed(() => `Level x${step.value}`);
const increment = () => {
count.value += step.value;
emits('update', count.value);
};
const methods = {
decrease() {
count.value -= step.value;
emits('update', count.value);
},
};
watch(count, (newVal) => {
step.value = Math.floor(newVal / 10) || 1;
});
</script>
If I wrote the equivalent logic directly in React, a pretty normal version would look like this:
interface Props { ... };
const HelloWorld = (props: Props) => {
const [step, setStep] = useState(1);
const [count, setCount] = useState(0);
const title = useMemo(() => `Level x${step}`, [step]);
const increment = useCallback(() => {
setCount((prev) => {
const next = prev + step;
props.onUpdate?.(next);
return next;
});
}, [step, props.onUpdate]);
const methods = useMemo(() => ({
decrease() {
setCount((prev) => {
const next = prev - step;
props.onUpdate?.(next);
return next;
});
},
}), [step, props.onUpdate]);
useEffect(() => {
setStep(Math.floor(count / 10) || 1);
}, [count]);
};
And here is the important part: VuReact does not "win" because the generated code is magically tiny. It wins because the developer no longer has to keep making all of those decisions manually at authoring time.
An abridged VuReact-style output looks like this:
// inferred from Vue props
type IHelloWorldProps = {
title?: string;
onUpdate?: (value: number) => void;
};
const HelloWorld = memo((props: IHelloWorldProps) => {
const step = useVRef(1);
const count = useVRef(0);
const title = useComputed(() => `Level x${step.value}`);
const increment = useCallback(() => {
count.value += step.value;
props.onUpdate?.(count.value);
}, [count.value, step.value, props.onUpdate]);
const methods = useMemo(() => ({
decrease() {
count.value -= step.value;
props.onUpdate?.(count.value);
},
}), [count.value, step.value, props.onUpdate]);
useWatch(count, (newVal) => {
step.value = Math.floor(newVal / 10) || 1;
});
});
export default HelloWorld;
The key comparison is not "which code is shorter?" It is "what manual maintenance burden keeps returning to the developer?"
| Metric | Handwritten React | Vue input + VuReact |
|---|---|---|
| Explicit optimization APIs |
memo, useMemo x2, useCallback, useEffect
|
0 written by the developer |
| Dependency array items to maintain | 6 | 0 |
| Extra maintenance-oriented boilerplate | ~18 lines | 0 |
| Output remains pure React | Yes | Yes |
That is the point I think matters most. VuReact is not just replacing syntax. It is moving a set of stability decisions from "developer memory and review discipline" into "compiler analysis and predictable output."
For a team, that means fewer rounds of:
- "Did we miss a dependency?"
- "Should this object be memoized?"
- "Did this callback become unstable after the last refactor?"
- "Is this still a normal React project once we are done?"
Where This Fits Best
VuReact makes the most sense when:
- your team already thinks comfortably in Vue
- you still need to ship React-compatible output
- you want a gradual migration path instead of a rewrite weekend
- you care about maintainable React output, not just a passing demo
It makes much less sense when:
- you expect a zero-convention tool that can convert every Vue edge case automatically
- you want to preserve every Vue runtime trick exactly as-is
- you are looking for a no-thought full rewrite codemod
So I would not position VuReact as "universal migration magic." I would position it as a very specific engineering choice for teams that want to keep Vue's authoring model while landing in the React ecosystem cleanly.
Final Note
What convinced me that VuReact is worth writing about is not that it can output React. A lot of tools can produce something that runs.
What makes it interesting is that it tries to preserve the part that usually gets expensive later: maintainability. It gives Vue-leaning developers a way to test, inspect, and ship React output without immediately signing up for every manual optimization and dependency-management chore that React often pushes back onto the author.
If this looks useful, inspect the generated output, read the docs, and take a look at the repo. If it feels like the kind of workflow your team could actually use, consider giving it a star.
Resources
- Docs: https://vureact.top
- GitHub: https://github.com/vureact-js/core
- Playground: https://codesandbox.io/p/github/vureact-js/example-customer-support-hub/master?import=true
Disclosure: I used AI assistance to help organize and polish this article, but I verified the technical details and claims myself.

Top comments (0)