Compilation Conventions
This page contains mandatory conventions. If not followed, the compilation output may not comply with React rules.
Using AI tools to assist and manage the compiler workflow can provide a significant advantage.
The compiler will try to offer friendly warnings for violations, and following these conventions is key to a successful migration.
A. File and Entry Conventions
- It is recommended to include only controllable directories in the
inputcompiler option. - It is strongly recommended to add the Vue entry file (such as
src/main.ts) toexclude. - Verify in a small directory first, then expand the scope.
- Remove any unused files that Vite may leave behind when generating a React project (such as
src/index.css,src/App.css, etc.), and also remove references to those files from the Reactmain.ts.
B. Script Conventions
- Components must use Vue 3
<script setup>syntax. - Macros / reactivity / lifecycle / hook APIs must be used at the top level and are prohibited inside conditionals, loops, nested functions, or single exports.
- Other JavaScript files should follow rule #2, but usage is allowed inside top-level functions.
<script setup> Conventions
✅ Valid Example
<script setup>
/*
Macros / reactivity / lifecycle / hook APIs must
only be used at the top level of <script setup>
*/
defineProps(...);
const refValue = ref();
const state = reactive();
const computedValue = computed();
watch(...);
onMounted(...);
watchEffect(...);
</script>❌ Invalid Example
<script setup>
/*
Using these APIs inside conditionals, loops, or nested functions
causes the transformed React hooks to violate positional rules
and eventually trigger runtime errors.
*/
if (condition) {
defineProps(...);
const refValue = ref();
}
function nested() {
const state = reactive();
watchEffect(...);
}
onMounted(() => {
const computedValue = computed();
});
/*
A single export can cause nested export
inside a React component function
*/
export const singleExport = ref();
</script>JavaScript File Conventions
✅ Valid Example
/*
Macros / reactivity / lifecycle / hook APIs should
only be used inside top-level functions in the file
*/
export function customHook() {
const refValue = ref();
const computedValue = computed();
onMounted(...);
watchEffect(...);
}❌ Invalid Example
/*
Using these APIs outside a top-level function,
such as inside conditionals, loops, or nested functions
*/
export function customHook() {
if (condition) {
const refValue = ref();
onMounted(...);
}
const nested = () => {
const computedValue = computed();
}
}
/*
An independent export can cause the transformed hook
to be detached from the React component scope
*/
export const state = reactive();💡 For script conversion reference, see Script Semantic Comparison.
C. Template Conventions
- Only Vue's official template directives are supported; unknown directives are not supported.
- Do not use Vue runtime magic properties such as
$attrs,$props,$emits, etc. - Props / emits / slots / attrs must be explicitly declared using
defineProps/defineEmits/defineSlots/useAttrs; implicit usage is prohibited.
Props / Emits / Slots / Attrs Conventions
✅ Valid Example
<script setup lang="ts">
/* Note: the example is written in TS, but JS is also supported */
const props = defineProps<Props>();
const emits = defineEmits<Emits>();
const attrs = useAttrs<Attrs>();
</script>
<template>
<!-- Use explicit declarations -->
<div v-if="props.condition" @click="emits('event')">
{{ props.value }}
</div>
<button v-bind="attrs"></button>
</template>❌ Invalid Example
<!-- Using Vue runtime magic properties -->
<div v-if="$props.condition" @click="$emit('event')">
{{ $props.value }}
</div>
<button v-bind="$attrs"></button>💡 For template conversion reference, see Template Semantic Comparison.
D. Style Conventions
- Only the first
styleblock is supported; multiplestyleblocks are not supported. - Do not use
cssVars. - Other CSS file conventions should follow rule #2.
✅ Valid Example
<style>
/*
Only the first style block is supported,
and cssVars are not allowed
*/
.class { ... }
</style>❌ Invalid Example
<style>
.class {
/* Using cssVars */
color: v-bind('color');
}
</style>
<!-- Multiple style blocks -->
<style></style>
<style></style>💡 For style conversion reference, see Style Semantic Comparison.
E. Routing Conventions
We provide the @vureact/router routing adaptation package, which fully mirrors Vue Router 4.x. In most cases, you do not need to change the Vue-side routing code, and the compiler will automatically handle adaptation. The routing entry file must export the router instance with export default, and the route entry file path must be specified in vureact.config.ts.
See Routing Adaptation for details.
✅ Valid Example
/*
Assume the routing entry file is src/router/index.ts.
It must export the router instance returned
by createRouter using export default.
*/
export default createRouter( ... );// vureact.config.ts
export default defineConfig({
router: {
/*
Specify the route entry file,
and the compiler will automatically handle route adaptation
*/
configFile: 'src/router/index.ts',
},
});❌ Invalid Example
If the routing entry file is not adapted according to the routing conventions, or if the routing entry file is not specified, the compiler cannot correctly handle route adaptation.
💡 For routing conversion reference, see Routing Semantic Comparison.
