@angular/router, react-router, svelte-routing, and vue-router are the standard routing solutions for their respective ecosystems (Angular, React, Svelte, and Vue). They handle navigation, URL synchronization, and component rendering without full page reloads. While they share the core goal of managing application state via the URL, they differ significantly in implementation details, configuration styles, and integration with their framework's lifecycle. @angular/router and vue-router are tightly coupled with their frameworks' dependency injection and reactivity systems, whereas react-router and svelte-routing rely more on component composition and store patterns respectively.
Routing is the backbone of any single-page application (SPA). It keeps the UI in sync with the URL, manages history, and controls which components render. While @angular/router, react-router, svelte-routing, and vue-router all solve this problem, they do so in ways that reflect the philosophy of their host frameworks. Let's look at how they handle the core challenges of modern web development.
How you declare paths determines how maintainable your app scales. Some prefer a central config file, while others like defining routes alongside components.
@angular/router uses a centralized configuration array.
// angular: app-routing.module.ts
const routes: Routes = [
{ path: 'users/:id', component: UserComponent },
{ path: 'about', component: AboutComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
react-router lets you define routes as components or config objects.
BrowserRouter and use Routes with Route components.// react: App.jsx
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/users/:id" element={<User />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
svelte-routing mixes routing components directly into your markup.
Router and Route components inside your main App component.<!-- svelte: App.svelte -->
<script>
import { Router, Route } from "svelte-routing";
import User from "./User.svelte";
import About from "./About.svelte";
</script>
<Router>
<Route path="users/:id" component={User} />
<Route path="about" component={About} />
</Router>
vue-router relies on a configuration array passed to the router instance.
routes array.// vue: router/index.js
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{ path: '/users/:id', component: User },
{ path: '/about', component: About }
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
Getting data from the URL (like an ID) is a daily task. Each framework exposes this data differently based on its reactivity model.
@angular/router injects route data via a service.
ActivatedRoute observable to get params.// angular: user.component.ts
import { ActivatedRoute } from '@angular/router';
constructor(private route: ActivatedRoute) {
this.route.params.subscribe(params => {
const id = params['id'];
// load user
});
}
react-router provides hooks for functional components.
useParams to get a simple object of parameters.// react: User.jsx
import { useParams } from "react-router-dom";
function User() {
const { id } = useParams();
return <div>User ID: {id}</div>;
}
svelte-routing exposes params via props on the component.
Route component passes a params prop to your component.<!-- svelte: User.svelte -->
<script>
export let params = {};
$: id = params.id;
</script>
<div>User ID: {id}</div>
vue-router makes the route object available via composition API or options.
useRoute in the setup function to access params.// vue: User.vue
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
const id = route.params.id;
return { id };
}
};
Securing pages (like admin dashboards) requires checking permissions before rendering. This is often called "route guarding."
@angular/router has a dedicated CanActivate interface.
// angular: auth.guard.ts
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
canActivate(): boolean {
return authService.isLoggedIn();
}
}
// In routes config
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
react-router uses wrapper components or loader functions.
Navigate if failed.loader functions to throw redirects.// react: ProtectedRoute.jsx
function ProtectedRoute({ children }) {
const isAuth = useAuth();
return isAuth ? children : <Navigate to="/login" />;
}
// Usage
<Route path="/admin" element={<ProtectedRoute><Admin /></ProtectedRoute>} />
svelte-routing handles protection via conditional rendering in routes.
<!-- svelte: App.svelte -->
<Route path="admin">
{#if isLoggedIn}
<Admin />
{:else}
<Navigate to="/login" />
{/if}
</Route>
vue-router supports global and per-route navigation guards.
beforeEnter on the route config.beforeEach guards for app-wide checks.// vue: router/index.js
const routes = [
{
path: '/admin',
component: Admin,
beforeEnter: (to, from) => {
if (!isLoggedIn) return '/login';
}
}
];
Sometimes you need to move the user to a new page after an action, like a form submit. Each library provides a way to trigger this via code.
@angular/router uses the Router service injection.
navigate method with an array of path segments.// angular: login.component.ts
constructor(private router: Router) {}
login() {
this.router.navigate(['/dashboard']);
}
react-router provides the useNavigate hook.
// react: Login.jsx
import { useNavigate } from "react-router-dom";
function Login() {
const navigate = useNavigate();
const submit = () => navigate("/dashboard");
return <button onClick={submit}>Login</button>;
}
svelte-routing exposes a navigate function from the package.
<!-- svelte: Login.svelte -->
<script>
import { navigate } from "svelte-routing";
function submit() {
navigate("/dashboard");
}
</script>
<button on:click={submit}>Login</button>
vue-router gives access to the router instance via useRouter.
push method on the router object.// vue: Login.vue
import { useRouter } from 'vue-router';
export default {
setup() {
const router = useRouter();
const submit = () => router.push('/dashboard');
return { submit };
}
};
Despite the syntax differences, these libraries solve the same fundamental problems. Here is where they align:
popstate events to handle browser back/forward buttons.// Conceptual example shared by all
window.addEventListener('popstate', () => {
// Update UI to match current URL
});
// React Example
<Route path="dashboard" element={<Dashboard />}>
<Route path="stats" element={<Stats />} />
</Route>
// Angular Example
{ path: 'dashboard', component: DashboardComponent, children: [
{ path: 'stats', component: StatsComponent }
]}
// Vue Example
const routes = [
{ path: '/heavy', component: () => import('./HeavyComponent.vue') }
];
// Angular Example
{ path: 'heavy', loadChildren: () => import('./heavy.module').then(m => m.HeavyModule) }
// Vue/React/Angular all support some form of this
router.beforeEach((to, from) => {
document.title = to.meta.title;
});
| Feature | @angular/router | react-router | svelte-routing | vue-router |
|---|---|---|---|---|
| Config Style | Centralized Array | Component Tree | Component Tree | Centralized Array |
| Param Access | Injected Service | Hooks (useParams) | Component Props | Composition API (useRoute) |
| Guards | CanActivate Interface | Wrapper Components / Loaders | Conditional Rendering | beforeEnter / Global Guards |
| Navigation | Router.navigate() | useNavigate() Hook | navigate() Function | router.push() |
| Framework | Angular | React | Svelte | Vue |
@angular/router is the most opinionated and feature-rich out of the box. It is built for large-scale enterprise apps where structure and strict typing are critical. If you are in the Angular ecosystem, there is no other choice, but it rewards you with powerful tools like resolvers and complex guard chains.
react-router prioritizes flexibility and composition. It fits the React philosophy of "just JavaScript." It is ideal for teams that want to define routes where they render them and prefer hooks over services. It adapts well to both simple sites and complex dashboards.
svelte-routing is the lightweight contender. It brings routing to Svelte without heavy abstractions. It is perfect for Svelte apps that need standard routing features without the boilerplate of larger frameworks. It feels very natural if you already know Svelte's prop system.
vue-router strikes a balance between configuration and reactivity. It offers the structure of Angular's config with the ease of Vue's reactivity. It is the go-to for Vue apps, providing robust features like named views and scroll behavior control with minimal setup.
Final Thought: Your choice is usually dictated by your framework choice. However, understanding how each handles data flow and protection helps you architect better applications within that ecosystem. Whether you prefer config arrays or component trees, the goal remains the same: keep the URL and UI in perfect harmony.
Choose vue-router if you are building a Vue.js application. It is the official router for Vue and is deeply integrated with Vue's reactivity system. It is the best choice for Vue projects needing dynamic route matching, nested views, and seamless transitions. It supports both Options API and Composition API patterns naturally.
Choose @angular/router if you are building an Angular application. It is not a standalone library but an integral part of the Angular platform. It excels in enterprise scenarios requiring complex guard logic, lazy loading modules, and deep integration with Angular's dependency injection system. It is the only viable choice for standard Angular apps.
Choose svelte-routing if you are building a Svelte application and need a router that feels native to Svelte's component model. It is suitable for projects where you want routing logic defined directly in your component markup using slots and props. It is a lightweight choice for Svelte apps that don't require the heavy feature set of a full framework router.
Choose react-router if you are building a React application. It is the community standard for managing location in React apps. It is ideal for projects that need flexible route definitions (either via components or config objects) and deep integration with React hooks. It works well for both single-page apps and server-rendered React architectures.
- This is the repository for Vue Router 4 (for Vue 3)
- For Vue Router 3 (for Vue 2) see vuejs/vue-router. To see what versions are currently supported, please refer to the Security Policy.
Vue Router is part of the Vue Ecosystem and is an MIT-licensed open source project with its ongoing development made possible entirely by the support of Sponsors. If you would like to become a sponsor, please consider:
Get started with the documentation.
Via CDN: <script src="https://unpkg.com/vue-router@4"></script>
In-browser playground on CodeSandbox
Add it to an existing Vue Project:
npm install vue-router@4
Please consult the Migration Guide.
See Contributing Guide.
Special thanks to BrowserStack for letting the maintainers use their service to debug browser specific issues.