Quick Start
Help developers get started in the shortest time and complete the compilation and conversion of a simple Vue project to a React project.
🎥 Check out the 2-minute demo below for a quick overview.
Overview
- What conventions the input SFC must follow for stable conversion
- What the output directory structure looks like
- The semantic correspondence between the output TSX and the original SFC
- The compiler automatically analyzes and appends React hook dependencies, eliminating the need for manual management
Step 0: Prepare a Vite + Vue Project
- Initialize a standard Vue + TS project using Vite:
npx create-vite@latest vue-app --template vue-tsWhen prompted
Install with npm and start now?, selectNo.You will see a project directory structure similar to the following:
vue-app/
├─ public/
├─ src/
│ ├─ assets/
│ ├─ components/
│ │ └─ HelloWorld.vue
│ ├─ App.vue
│ ├─ main.ts
│ └─ style.css
├─ index.html
├─ package.json
├─ tsconfig.json
├─ vite.config.ts
└─ ...Step 1: Installation
- Navigate to the directory and install project dependencies:
cd vue-app
npm install- Install the VuReact compiler core:
npm install -D @vureact/compiler-coreStep 2: Configure the Compiler
Create a vureact.config.ts file in the vue-app directory:
// vue-app/vureact.config.ts
import { defineConfig } from '@vureact/compiler-core';
export default defineConfig({
// Input path containing Vue files to compile; single file 'xxx.vue' is also supported
input: './src',
// Exclude Vue entry files to avoid semantic conflicts
exclude: ['src/main.ts'],
output: {
// Workspace directory for storing compilation artifacts and cache
workspace: '.vureact',
// Output directory name
outDir: 'react-app',
// Automatically initialize a Vite React environment
bootstrapVite: true,
},
});In fact, besides exclude which must be specified manually, all other options use the default values shown in the example configuration—no additional configuration is needed.
Step 3: Write the Vue Component
3.1 Implement a Simple Counter
Replace the original HelloWorld.vue with the counter component code:
<!-- src/components/HelloWorld.vue -->
<template>
<section class="counter-card">
<h1>{{ props.title }}</h1>
<h2>
<span class="vureact">VuReact</span>
➕
<span class="vue">Vue</span>
🟰
<span class="react">React</span>
({{ count }})
</h2>
<p>{{ title }}</p>
<button @click="increment">+1</button>
<button @click="methods.decrease">-1</button>
</section>
</template>
<script setup lang="ts">
// @vr-name: HelloWorld
import { computed, ref, watch } from 'vue';
// In addition to the special comment at the top, component names can also be defined using macros
// defineOptions({ name: 'HelloWorld' });
// defineProps must be used to define props
const props = defineProps<{ title?: string }>();
// defineEmits must be used to define emits
const emits = defineEmits<{
(e: 'update', value: number): void;
}>();
const step = ref(1);
const count = ref(0);
const title = computed(() => `阶数: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>
<!-- VuReact supports processing Less and Sass -->
<style scoped>
.counter-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 12px;
.vureact {
color: #9932cc;
}
.vue {
color: #42b883;
}
.react {
color: #61dafb;
}
}
</style>3.2 Update the App.vue to Use the HelloWorld Component
<!-- src/App.vue -->
<script setup lang="ts">
// @vr-name: App
import HelloWorld from './components/HelloWorld.vue';
</script>
<template>
<HelloWorld
title="Counter"
@update="(v) => {console.log(v)}"
/>
</template>Step 4: Compile to a React Project
Method 1: Using npx
Run the following in the vue-app directory:
# Full/incremental compilation
npx vureact build
# Or compile in watch mode
npx vureact watchMethod 2: Using npm scripts
Add the following scripts to your package.json:
"scripts": {
"vr:build": "vureact build",
"vr:watch": "vureact watch"
}npm run vr:buildStep 5: View the Output Directory Structure
Output to the vue-app/.vureact workspace directory (illustrative):
vue-app/
├── .vureact/ # Workspace (generated by compilation)
│ ├── cache/ # Compilation cache
│ ├── react-app/ # Generated Vite + React project
│ │ ├── src/
│ │ │ ├── components/
│ │ │ │ ├── HelloWorld.tsx
│ │ │ │ └── HelloWorld-[hash].css
│ │ │ ├── App.tsx
│ │ │ ├── index.css
│ │ │ ├── main.tsx
│ │ │ └── style.css
│ │ └── package.json
│ │ └── tsconfig.json
│ │ └── vite.config.ts
│ │ └── ...
│ │
├── src/ # Original Vue source code
├── ...
└── vureact.config.js # VuReact configuration fileStep 6: Run the React Application
- Navigate into the
react-appdirectory:
cd .vureact/react-app- Install dependencies:
npm run install- Start the project:
npm run devNote: When you open the page, you may notice style differences from the Vue version. This is because Vite's default React initialization injects its own
index.cssintomain.tsx. You can adjust it manually.
If you encounter any issues, refer to the FAQ section.
Step 7: Compare the Generated Output
Below is a formatted typical output (slightly simplified for explanation; actual hashes and property names depend on your local build):
import { useComputed, useVRef, useWatch } from '@vureact/runtime-core';
import { memo, useCallback, useMemo } from 'react';
import './HelloWorld-ebf8d8dc.css';
// VuReact automatically generates based on defineProps and defineEmits
export type IHelloWorldProps = {
title?: string;
} & {
onUpdate?: (value: number) => void;
};
// Automatically use memo to optimize the component
const HelloWorld = memo((props: IHelloWorldProps) => {
// ref/computed converted to equivalent adapter API
const step = useVRef(1);
const count = useVRef(0);
const title = useComputed(() => `阶数:x${step.value}`);
// Automatically analyze dependencies in top-level arrow functions and append useCallback optimization
const increment = useCallback(() => {
count.value += step.value;
props.onUpdate?.(count.value); // emits 转换
}, [count.value, step.value, props.onUpdate]);
// Automatically analyze dependencies in top-level variables and append useMemo optimization
const methods = useMemo(
() => ({
decrease() {
count.value -= step.value;
props.onUpdate?.(count.value);
},
}),
[count.value, step.value, props.onUpdate],
);
// watch converted to equivalent adapter API
useWatch(count, (newVal) => {
step.value = Math.floor(newVal / 10) || 1;
});
return (
<>
<section className="counter-card" data-css-ebf8d8dc>
<h1 data-css-ebf8d8dc>{props.title}</h1>
<h2 data-css-ebf8d8dc>
<span class="vureact" data-css-ebf8d8dc>VuReact</span>
➕
<span class="vue" data-css-ebf8d8dc>Vue</span>
🟰
<span class="react" data-css-ebf8d8dc>React</span>
({count.value})
</h2>
{/* Automatically append .value to ref access */}
<p data-css-ebf8d8dc>{title.value}</p>
<button onClick={increment} data-css-ebf8d8dc>
+1
</button>
<button onClick={methods.decrease} data-css-ebf8d8dc>
-1
</button>
</section>
</>
);
});
// Automatically keep component export
export default Counter;CSS file content:
.counter-card[data-css-abc123] {
border: 1px solid #ddd;
border-radius: 8px;
padding: 12px;
}Key Observations
// @vr-name: Counter— This special comment defines the component namedefinePropsanddefineEmitsare converted to typed TypeScript component interfaces- Non-pure UI display components are automatically wrapped with
memo ref/computed/watchare converted to equivalent runtime adapter APIs (useVRef/useComputed/useWatch)- Template event callbacks generate React-compatible event handlers like
onClick - Top-level arrow functions are automatically analyzed for dependencies and wrapped with
useCallback - Top-level variable declarations are automatically analyzed for dependencies and wrapped with
useMemo .valueis appended toref/computedvalues used in JSXscopedstyles generate hashed CSS files and apply scoped attributes to elements
Summary
Through the steps above, you have completed the full compilation process from a Vue SFC project to a React project. Let's recap the entire flow:
- Initialize the project: Create a standard Vue + TS project using Vite
- Install the compiler: Add the
@vureact/compiler-coredependency - Write the configuration: Use
vureact.config.tsto specify input, exclusion, and output rules - Write the component: Follow conventions (
@vr-namecomment,defineProps/defineEmitsmacros) when authoring SFCs - Execute compilation: Use the CLI command for one-click conversion
- Run the output: Start the generated React project directly and verify the results
VuReact provides the following core conversion capabilities:
- Vue template syntax → React JSX (
v-if/v-slot/v-model/<slot>etc.) - Composition API → React Hooks (
ref→useVRef,computed→useComputed) - Reactive dependency analysis → Automatic injection of
useCallback/useMemodependency arrays - Component communication → Props type inference + event callback mapping
- Style processing → Scoped CSS / CSS Modules / preprocessor support all-in-one compilation
Related Resources
- @vureact/runtime-core: Provides React-equivalent Vue built-in components, core Composition API, etc.
- @vureact/router: Supports Vue Router 4.x → React Router DOM 7.9+ conversion
Next Steps
After completing the Getting Started guide, we recommend continuing with the following sections:
- ESLint Rule Conflicts: Understand conflicts between reactive hooks and ESLint React Hooks rules, and their solutions
- Compilation Conventions: Follow the compiler conventions of VuReact to align with best practices
- Compiler Configuration: Learn more about VuReact configuration API
- Real-World Projects: Master large-scale migration workflows through real project examples (admin dashboard, collaborative backend)
- Semantic Compilation Comparison: Understand how Vue is compiled into React code, and the currently supported API and syntax scope
