vue-tiny-router

A lightweight Vue 3 router (~2.2 kB Brotli) with params, query, guards, nested layouts, lazy loading, and redirects
4,201 6
Install
npm install vue-tiny-router
Latest Version:1.9.0
Vue:3
License:MIT
Last Updated:Apr 23, 2026
Links: GitHub  ·  npm
Maintainer: makio64

vue-tiny-router

CI bundle size license

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 entry
    • back() / forward() / go(n) - History navigation
    • beforeEach(fn) / afterEach(fn) - Global navigation hooks
    • route / path - Reactive current route strings
    • params - Reactive params object
    • query - Parsed query object
    • hash - Current hash without #
    • name - Current route name
    • matched - Whether a route matched
    • meta - Reactive route metadata
    • component - Current matched component (non-reactive reference)
  • useRoute() - Returns an object with:
    • route / path - Reactive current route strings
    • params - Reactive params object
    • query - Parsed query object
    • hash - Current hash without #
    • name - Current route name
    • matched - Whether a route matched
    • meta - 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 ✅

See full migration guide →

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 beforeEnter guards
  • 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

viewlogic

A lightweight, file-based routing system for Vue 3 applications with zero build...

4,615 0
vue-router-spa-tabs

Tabbed Navigation for Vue Router in Single Page Applications

985 0
@composy/router-vue

Vue 3 router library with enhanced features, built on vue-router

0
@esmx/router-vue

Vue integration for @esmx/router - A universal router that works seamlessly with...

8,720 680
vue-router-storage

Router storage & resolve solution for Vue.js 2 & vue-router 2

931 89

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