DEV Community

Ryan John
Ryan John

Posted on • Originally published at vureact.top

How does VuReact compile Vue Router to React Router?

VuReact is a compiler toolchain for migrating from Vue to React — and for writing React with Vue 3 syntax. Today we take a macro-level look at Vue Router, examining how Vue's routing components, APIs, and entry structure are compiled into React routing code by VuReact.

Also, this article only covers a subset of routing components and APIs. The full adapter includes typed route interfaces and more. For details, check the VuReact Router documentation.

Before We Start

To keep the examples easy to read, this article follows two simple conventions:

  1. All Vue and React snippets focus on core logic only, with full component wrappers and unrelated configuration omitted.
  2. The discussion assumes you are already familiar with the Vue Router API usage and core behavior.

Compilation Mapping

Router components: <router-link> / <router-view>

Vue's router components are mapped to adapter components provided by @vureact/router in React.

  • Vue
<template>
  <router-link to="/home">Home</router-link>
  <router-view />
</template>
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
import { RouterLink, RouterView } from '@vureact/router';

return (
  <>
    <RouterLink to="/home">Home</RouterLink>
    <RouterView />
  </>
);
Enter fullscreen mode Exit fullscreen mode

RouterLink in React supports the same Vue-style features, including string to, object to, activeClassName, customRender, and more. RouterView renders the currently matched route component and preserves the execution order of nested routes, route guards, and meta fields.


Route configuration: createRouter + history

Vue Router's creation API maintains semantic consistency in VuReact, with only the import source replaced by @vureact/router.

  • Vue
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';

export default createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
  ],
});
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
import { createRouter, createWebHistory } from '@vureact/router';
import Home from './views/Home';

export default createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
  ],
});
Enter fullscreen mode Exit fullscreen mode

This demonstrates:

  • API names like createRouter / createWebHistory remain unchanged
  • Only the import path is replaced with @vureact/router
  • Vue Router's route records, nested routes, and meta fields are preserved directly

Entry injection: RouterProvider

When automatic adaptation is enabled, VuReact adjusts the entry file after compilation, replacing the original <App /> with the route instance's RouterProvider.

  • Generated React entry file
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import RouterInstance from './router/index';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterInstance.RouterProvider />
  </StrictMode>,
);
Enter fullscreen mode Exit fullscreen mode

This entry structure reflects the macro-level changes from Vue routing to React routing adaptation:

  • The Vue route configuration file continues to serve as the route instance entry
  • The React entry mounts the router context via RouterProvider
  • Business routing logic does not need to be rewritten — only the route definitions need to be well-structured

Runtime APIs: useRouter / useRoute

Vue's Composition API routing hooks retain the same semantics in React.

  • Vue
const router = useRouter();
const route = useRoute();

const goHome = () => {
  router.push('/home');
};
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
import { useRouter, useRoute } from '@vureact/router';

const router = useRouter();
const route = useRoute();

const goHome = useCallback(() => {
  router.push('/home');
}, [router]);
Enter fullscreen mode Exit fullscreen mode

useRouter() and useRoute() continue to support programmatic navigation, parameter reading, meta fields, and more, with usage semantics consistent with Vue Router's Composition API.

Automatic vs Manual Adaptation

Automatic adaptation

When the compiler detects the use of Vue Router in a project, it automatically:

  • Replaces import ... from 'vue-router' with import ... from '@vureact/router'
  • Converts the route configuration file output to a @vureact/router route instance
  • Rewrites the entry file to render via RouterProvider

Configuration example:

import { defineConfig } from '@vureact/compiler-core';

export default defineConfig({
  router: {
    // Path to the route entry file (where createRouter() is called and exported by default)
    configFile: 'src/router/index.ts',
  },
});
Enter fullscreen mode Exit fullscreen mode

Manual adaptation

The following approach is a general recommendation. Please adjust implementation details based on your actual project requirements.

When the output.bootstrapVite or router.autoSetup option is set to false, automatic adaptation is not available and you will need to do it manually:

  • Export the Vue Router createRouter() instance
  • In the React entry file, replace the original <App /> rendering with the <RouterProvider /> component provided by the @vureact/router route instance

The core of manual adaptation is: preserve Vue Router's route definitions and nested route structure, export the router instance, and replace the React entry rendering approach.

Related Links

Top comments (0)