Skip to content

Route Configuration

Route configuration is the foundation of Uni Router. This chapter details each field of RouteConfig, route matching rules, the relationship with pages.json, and route organization for large projects.

RouteConfig Details

Each route configuration item corresponds to a page in pages.json:

ts
interface RouteConfig {
  path: string              // Page path (required)
  name?: string             // Route name (recommended)
  meta?: RouteMeta          // Route meta info
  beforeEnter?: NavigationGuard | NavigationGuard[]  // Route-exclusive guard
  [key: string]: any        // Custom extension properties
}

path

Page path, must match the declaration in pages.json exactly (without leading /):

ts
// pages.json
{
  "pages": [
    { "path": "pages/index/index" },
    { "path": "pages/about/about" }
  ]
}

// Route configuration
const routes: RouteConfig[] = [
  { path: 'pages/index/index', name: 'home' },
  { path: 'pages/about/about', name: 'about' }
]

Path Consistency

path must match pages.json exactly, otherwise route matching fails. Common errors:

ts
// ❌ Error: missing pages/ prefix
{ path: 'about/about' }

// ❌ Error: extra leading /
{ path: '/pages/about/about' }

// ❌ Error: incomplete path
{ path: 'pages/about' }

// ✅ Correct
{ path: 'pages/about/about' }

Subpackage Paths

Subpackage page paths need to include the subpackage root directory:

json
// pages.json
{
  "subPackages": [
    {
      "root": "subpkg",
      "pages": [
        { "path": "detail/detail" }
      ]
    }
  ]
}
ts
// Route configuration: path = subpackage root + page path
const routes: RouteConfig[] = [
  { path: 'subpkg/detail/detail', name: 'detail' }
]

// Navigation
await router.push({ name: 'detail' })

name

Route name, used for named navigation. Strongly recommend configuring a unique name for each route.

ts
// Named navigation (recommended)
await router.push({ name: 'about' })

// Path navigation (not recommended, need to modify all callsites when path changes)
await router.push({ path: 'pages/about/about' })

Benefits of Naming

  1. Decoupled paths: When path changes, only modify route config, no need to modify business code
  2. Type safety: With auto-generation, get type hints for names
  3. Readability: { name: 'user-profile' } is clearer than 'pages/user/profile/profile'

Duplicate Names

If duplicate name is defined, the later one overwrites the earlier one with a warning:

ts
const routes = [
  { path: 'pages/a/a', name: 'detail' },
  { path: 'pages/b/b', name: 'detail' } // ⚠️ Overwrites the former
]

router.push({ name: 'detail' }) // Navigates to pages/b/b

meta

Route meta information, see Route Meta.

beforeEnter

Route-exclusive guard, see Route Guards - beforeEnter.

Creating a Router

ts
import { createRouter } from '@meng-xi/uni-router'

const router = createRouter({
  routes: [
    {
      path: 'pages/index/index',
      name: 'home',
      meta: { isTab: true, title: 'Home' }
    },
    {
      path: 'pages/about/about',
      name: 'about',
      meta: { title: 'About', requireAuth: true }
    }
  ],
  strict: true,           // Strict mode
  interceptUniApi: true,  // Intercept native API
  guardTimeout: 15000,    // Guard timeout
  readyTimeout: 5000      // Ready timeout
})

Configuration Options Details

OptionTypeDefaultDescription
routesRouteConfig[]-Route configuration array (required)
strictbooleantrueStrict mode, unmatched named routes throw error
interceptUniApibooleanfalseIntercept uni.navigateTo and other native APIs
guardTimeoutnumber10000Guard timeout (ms)
readyTimeoutnumber5000Router ready timeout (ms)

strict Option

  • true (default): Unmatched named routes throw ROUTE_NOT_FOUND error
  • false: Unmatched named routes only warn, and fall back to using name as path
ts
// Strict mode
const router = createRouter({ routes, strict: true })
await router.push({ name: 'not-exist' }) // Throws error

// Lenient mode
const router = createRouter({ routes, strict: false })
await router.push({ name: 'not-exist' }) // Warns, tries to navigate to /not-exist

Recommend Strict Mode

Production environments should use strict: true to catch route configuration errors early. Can temporarily set to false during development for easier debugging.

guardTimeout Option

Guard execution timeout. If guards have time-consuming operations like network requests, increase it:

ts
const router = createRouter({
  routes,
  guardTimeout: 30000 // Guards have network requests, 30 seconds
})

When timeout occurs, navigation is cancelled and throws NAVIGATION_CANCELLED.

readyTimeout Option

Router initialization timeout for waiting page stack to be ready. Usually no need to modify.

Route Matching Rules

Uni Router supports both path and name matching.

Path Matching

ts
// String form
router.push('pages/about/about')
router.push('/pages/about/about') // Auto-adds /
router.push('pages/about/about?id=1') // With query

// Object form
router.push({ path: 'pages/about/about' })
router.push({ path: 'pages/about/about', query: { id: '1' } })

Path Normalization

ts
// The following are equivalent
router.push('pages/about/about')
router.push('/pages/about/about')
router.push('pages/about/about/') // Trailing / is ignored

Query Parsing

ts
// Query in URL string is parsed
router.push('pages/about/about?id=1&tab=info')
// Equivalent to
router.push({ path: 'pages/about/about', query: { id: '1', tab: 'info' } })

Name Matching

ts
// Basic usage
router.push({ name: 'about' })

// With query
router.push({ name: 'about', query: { id: '1' } })

// With params (complex data)
router.push({ name: 'detail', params: { item: largeObject } })

Mixed Usage

ts
// ❌ Not recommended: path and name used together (name takes priority)
router.push({ path: 'pages/about/about', name: 'about' })

// ✅ Recommended: choose one
router.push({ name: 'about' })
// or
router.push({ path: 'pages/about/about' })

Relationship with pages.json

Uni Router does not replace pages.json, but works with it:

Responsibilitypages.jsonUni Router
Page registration✅ Must declare❌ Not responsible
Route navigationuni.navigateTo etc.push / replace / back
Route guards❌ Not supportedbeforeEach etc.
Route meta❌ Not supportedmeta field
Named routes❌ Not supportedname field
Page stylesstyle❌ Not responsible
TabBar configtabBar❌ Not responsible

Configuration Consistency

json
// pages.json
{
  "pages": [
    { "path": "pages/index/index" },
    { "path": "pages/about/about" }
  ],
  "tabBar": {
    "list": [
      { "pagePath": "pages/index/index", "text": "Home" }
    ]
  }
}
ts
// Route configuration must match pages.json
const routes = [
  { path: 'pages/index/index', name: 'home', meta: { isTab: true } },
  { path: 'pages/about/about', name: 'about' }
]

isTab Consistency

meta.isTab must be consistent with pages.json's tabBar.list:

  • TabBar pages must set isTab: true, otherwise using navigateTo to jump to TabBar pages will fail
  • Non-TabBar pages should not set isTab: true, otherwise using switchTab to jump to non-TabBar pages will fail

Route Organization

Single File (Small Projects)

ts
// router/index.ts
import { createRouter } from '@meng-xi/uni-router'

const router = createRouter({
  routes: [
    { path: 'pages/index/index', name: 'home', meta: { isTab: true } },
    { path: 'pages/about/about', name: 'about' },
    { path: 'pages/login/login', name: 'login' }
  ]
})

export default router

Modular Organization (Medium/Large Projects)

Split routes by business module:

src/
├── router/
│   ├── index.ts          # Router instance
│   └── routes.ts         # Aggregated routes
├── modules/
│   ├── user/
│   │   └── routes.ts     # User module
│   ├── order/
│   │   └── routes.ts     # Order module
│   └── product/
│       └── routes.ts     # Product module
ts
// modules/user/routes.ts
import type { RouteConfig } from '@meng-xi/uni-router'

export const userRoutes: RouteConfig[] = [
  { path: 'pages/user/user', name: 'user', meta: { isTab: true, title: 'Profile' } },
  { path: 'pages/profile/profile', name: 'profile', meta: { requireAuth: true } },
  { path: 'pages/settings/settings', name: 'settings', meta: { requireAuth: true } }
]
ts
// router/routes.ts
import { userRoutes } from '@/modules/user/routes'
import { orderRoutes } from '@/modules/order/routes'
import { productRoutes } from '@/modules/product/routes'

export const routes: RouteConfig[] = [
  { path: 'pages/index/index', name: 'home', meta: { isTab: true, title: 'Home' } },
  { path: 'pages/login/login', name: 'login' },
  ...userRoutes,
  ...orderRoutes,
  ...productRoutes
]

Use @meng-xi/vite-plugin to auto-generate route configurations and type declarations from pages.json:

ts
// vite.config.ts
import uniRouter from '@meng-xi/vite-plugin'

export default {
  plugins: [
    uniRouter({
      pagesJsonPath: 'src/pages.json',
      outputDir: 'src/router'
    })
  ]
}

See Auto Generate Routes.

Common Configuration Errors

1. Path Inconsistent with pages.json

ts
// ❌ pages.json has pages/about/about, route config is wrong
{ path: 'pages/about', name: 'about' }

// ✅ Consistent
{ path: 'pages/about/about', name: 'about' }

2. Forgot to Set isTab

ts
// ❌ TabBar page without isTab
{ path: 'pages/user/user', name: 'user' }
router.push({ name: 'user' }) // Uses navigateTo to jump to TabBar page, fails

// ✅ Set isTab
{ path: 'pages/user/user', name: 'user', meta: { isTab: true } }
router.push({ name: 'user' }) // Uses switchTab, succeeds

3. Duplicate name

ts
// ❌ Duplicate name
const routes = [
  { path: 'pages/a/a', name: 'detail' },
  { path: 'pages/b/b', name: 'detail' } // Overwrites former
]

// ✅ Unique name
const routes = [
  { path: 'pages/a/a', name: 'detail-a' },
  { path: 'pages/b/b', name: 'detail-b' }
]

4. Subpackage Path Error

ts
// ❌ Subpackage path doesn't include subpackage root
{ path: 'detail/detail', name: 'detail' } // Subpackage root is subpkg

// ✅ Includes subpackage root
{ path: 'subpkg/detail/detail', name: 'detail' }

Next Steps

Released under the MIT License.