vue-tiny-router
vue-tiny-router
A lightweight Vue 3 router. ~2.2 kB Brotli with the common SPA router features most apps need.
Why vue-tiny-router?
- 🤏 Tiny: ~2.2 kB Brotli
- ⚡ Fast: Minimal overhead, maximum performance
- 🎯 Simple: Easy setup, intuitive API
- 💪 Complete: Route params, query, names, guards, nested layouts, lazy loading, redirects
How It Compares
| Router | Best For | Why choose vue-tiny-router? |
|---|---|---|
vue-router |
Large Vue apps needing every router feature | vue-tiny-router covers common Vue SPA routing at a fraction of the size |
Quick Start
1. Install
npm install vue-tiny-router
2. Setup
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { TinyRouterInstall } from 'vue-tiny-router'
createApp(App)
.use(TinyRouterInstall)
.mount('#app')
3. Configure Routes
<!-- App.vue -->
<template>
<TinyRouter :routes="routes" />
</template>
<script>
import { TinyRouter } from 'vue-tiny-router'
import Home from './views/Home.vue'
import Profile from './views/Profile.vue'
import NotFound from './views/NotFound.vue'
export default {
components: { TinyRouter },
data() {
return {
routes: [
{ path: '/', component: Home },
{ path: '/profile/:id', component: Profile },
{ path: '/*', component: NotFound } // catch-all 404,
]
}
}
}
</script>
4. Navigate
<template>
<button @click="$router.push('/')">Home</button>
<button @click="$router.push('/profile/123')">Profile</button>
</template>
5. Composition API (setup)
Use the provided composables in <script setup> or setup():
<script setup>
import { TinyRouter, useRouter, useRoute } from 'vue-tiny-router'
const router = useRouter()
const route = useRoute()
function goUser(id) {
router.push(`/profile/${id}`)
}
</script>
<template>
<TinyRouter :routes="routes" />
<div>Current: {{ route.route }}</div>
<div>User id: {{ route.params.id }}</div>
<button @click="goUser('42')">Go user 42</button>
<button @click="router.push('/')">Home</button>
<button @click="router.push('/profile/123')">Profile</button>
</template>
That's it! 🎉
API Reference
Router Methods
$router.push(path | location)- Navigate to a route (adds history entry)$router.replace(path | location)- Navigate without adding history entry$router.back()- Go back in history$router.forward()- Go forward in history$router.go(n)- Go to a specific history entry$router.beforeEach(fn)- Register a global guard$router.afterEach(fn)- Register an after-navigation hook$router.route- Current route path$router.params- Route parameters object$router.query- Parsed query object$router.meta- Current route metadata
Composables
useRouter()- Returns an object with:push(path | location)- Navigate programmatically (adds history entry)replace(path | location)- Navigate without adding history entryback()/forward()/go(n)- History navigationbeforeEach(fn)/afterEach(fn)- Global navigation hooksroute/path- Reactive current route stringsparams- Reactive params objectquery- Parsed query objecthash- Current hash without#name- Current route namematched- Whether a route matchedmeta- Reactive route metadatacomponent- Current matched component (non-reactive reference)
useRoute()- Returns an object with:route/path- Reactive current route stringsparams- Reactive params objectquery- Parsed query objecthash- Current hash without#name- Current route namematched- Whether a route matchedmeta- Reactive route metadata
Component Props
<TinyRouter
:routes="routes" // Required: Array of route objects
:redirects="redirects" // Optional: Redirect mappings
mode="history" // Optional: "history", "hash", or "memory"
:memoryMode="false" // Optional: legacy shortcut for mode="memory"
:scrollSmooth="false" // Optional: smooth scrolling on navigation
/>
Base path (subpath deployments)
If your app is served from a subpath (e.g. example.com/jsmap/), vue-tiny-router automatically reads Vite's import.meta.env.BASE_URL — no config needed. Just set base in vite.config.js:
// vite.config.js
export default { base: '/jsmap/' }
Routes stay app-relative (/, /about, /user/:id) — the router strips the base prefix when matching and re-adds it when writing to history. For non-Vite bundlers, override the basePath ref before mount:
import { basePath } from 'vue-tiny-router'
basePath.value = '/jsmap/'
Advanced Features
Route Parameters
Access dynamic route segments:
// Route: /user/:id
// URL: /user/123
this.$router.params.id // "123"
Query Strings
Query strings are parsed into a small object and can also be written through object navigation:
router.push({ path: '/search', query: { q: 'vue', page: 2 } })
route.query.q // "vue"
Named Routes
Add name to a route and navigate with params:
const routes = [
{ path: '/user/:id', name: 'user', component: User }
]
router.push({ name: 'user', params: { id: 42 } })
Route Meta
Attach metadata to routes for page titles, auth checks, etc:
const routes = [
{ path: '/', component: Home, meta: { title: 'Home' } },
{ path: '/admin', component: Admin, meta: { requiresAuth: true } }
]
// Access in components
const route = useRoute()
document.title = route.meta.title
Route Guards
Prevent navigation or add animations:
export default {
beforeRouteLeave(next, to) {
// Do something async, then call next()
this.saveData().then(next)
}
}
Global guards are return-based to stay compact:
const remove = router.beforeEach((to, from) => {
if (to.meta.requiresAuth && !isLoggedIn()) return '/login'
if (hasUnsavedChanges()) return false
})
Nested Layouts
Use children for nested layouts. Parent components render children through their default slot:
const routes = [
{
path: '/user/:id',
component: UserLayout,
children: [
{ path: 'settings', component: UserSettings }
]
}
]
Lazy Loading
Reduce initial bundle size:
import { defineAsyncComponent } from 'vue'
const routes = [
{
path: '/heavy',
component: defineAsyncComponent(() => import('./HeavyComponent.vue'))
}
]
Redirects
const redirects = {
'/old-path': '/new-path',
'/home': '/'
}
Default Routes
import { defaultRoute } from 'vue-tiny-router'
defaultRoute.value = '/dashboard'
Memory Mode
Perfect for embedded apps or testing:
<TinyRouter :routes="routes" :memoryMode="true" />
Hash Mode
Use hash URLs for static hosting:
<TinyRouter :routes="routes" mode="hash" />
Automatic Link Interception
vue-tiny-router automatically intercepts clicks on <a> tags. If the link's destination is a route managed by the router, it will prevent a page reload and handle it as an in-app navigation. For all other links (external sites or unhandled paths), it will allow the browser's default behavior. No configuration is needed.
Migration from vue-router
Most common patterns work the same:
| vue-router | vue-tiny-router |
|---|---|
$router.push() |
$router.push() ✅ |
$router.replace() |
$router.replace() ✅ |
$router.back() |
$router.back() ✅ |
$router.go(n) |
$router.go(n) ✅ |
$route.params |
$router.params ✅ |
$route.query |
$router.query ✅ |
$route.meta |
$router.meta ✅ |
| Named routes | Named routes ✅ |
| Nested routes | Nested layout routes ✅ |
| Global guards | Global guards ✅ |
beforeRouteLeave |
beforeRouteLeave ✅ |
| Lazy loading | Lazy loading ✅ |
Example & Documentation
🎯 Live Example
pnpm run dev
The example demonstrates all features including:
- Route parameters
- Query strings
- Named routes
- Route guards
- Nested layouts
- Hash mode
- Anchor links
- Memory mode
- Redirects
📚 Full Documentation
# Run the VitePress documentation
pnpm run docs:dev
Or view online: Vue Tiny Router Docs
Browser Support
Works in all modern browsers that support ES6+ and the History API.
Limitations
This library is intentionally tiny and focuses on the 80% use cases:
- No named views
- No route-level
beforeEnterguards - No advanced scroll behavior callback
- No Vue Router DevTools integration
If you need these features, consider using vue-router.
Contributing
Keep it tiny! When contributing:
- Maintain minimal bundle size
- Ensure all tests pass
- Follow the simple API design
Run the full development setup:
# Run tests
pnpm test
# Check bundle size
pnpm run size:check
# Run example app
pnpm run example:dev
# Run documentation
pnpm run docs:dev
License
MIT
Related Packages
A lightweight, file-based routing system for Vue 3 applications with zero build...
Vue integration for @esmx/router - A universal router that works seamlessly with...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.9.0 | ^3.0.0 | MIT | |
| 1.8.1 | ^3.0.0 | MIT | |
| 1.8.0 | ^3.0.0 | MIT | |
| 1.7.1 | ^3.0.0 | MIT | |
| 1.7.0 | ^3.0.0 | MIT | |
| 1.6.0 | ^3.0.0 | MIT | |
| 1.5.0 | ^3.0.0 | MIT | |
| 1.4.0 | ^3.0.0 | MIT | |
| 1.3.2 | ^3.0.0 | MIT | |
| 1.3.1 | ^3.0.0 | MIT | |
| 1.3.0 | ^3.0.0 | MIT | |
| 1.2.0 | ^3.0.0 | MIT | |
| 1.1.0 | ^3.0.0 | MIT | |
| 1.0.8 | ^3.0.0 | MIT | |
| 1.0.7 | ^3.0.0 | MIT | |
| 1.0.6 | ^3.0.0 | MIT | |
| 1.0.5 | ^3.0.0 | MIT | |
| 1.0.4 | ^3.0.0 | MIT | |
| 1.0.3 | ^3.0.0 | MIT | |
| 1.0.2 | ^3.0.0 | MIT | |
| 1.0.1 | ^3.0.0 | MIT | |
| 1.0.0 | ^3.0.0 | MIT |