All skills
vuejs-ai avatar

/vue-router-best-practices

@bc922e4 official
by Vue AIvuejs-ai/skills2.9k stars
167

Vue Router 4 patterns, navigation guards, route params, and route-component lifecycle interactions.

Use this Skill: https://skilld.dev/gh/vuejs-ai/skills/vue-router-best-practices

This session only. Nothing lands on disk.

referencerouter-navigation-guard-next-deprecated.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Vue Router Navigation Guard next() Function Deprecated

Impact: HIGH - The third next() argument in navigation guards is deprecated in Vue Router 4. While still supported for backward compatibility, using it incorrectly is one of the most common sources of bugs: calling it multiple times, forgetting to call it, or calling it conditionally without proper logic.

Task Checklist

  • Refactor guards to use return-based syntax instead of next()
  • Remove all next() calls from navigation guards
  • Use async/await pattern for asynchronous checks
  • Return false to cancel, return route to redirect, return nothing to proceed

The Problem

// WRONG: Using deprecated next() function
router.beforeEach((to, from, next) => {
  if (!isAuthenticated) {
    next('/login')  // Easy to forget this call
  }
  // BUG: next() not called when authenticated - navigation hangs!
})

// WRONG: Multiple next() calls
router.beforeEach((to, from, next) => {
  if (!isAuthenticated) {
    next('/login')
  }
  next()  // BUG: Called twice when not authenticated!
})

// WRONG: next() in async code without proper handling
router.beforeEach(async (to, from, next) => {
  const user = await fetchUser()
  if (!user) {
    next('/login')
  }
  next()  // Still gets called even after redirect!
})

Solution: Use Return-Based Guards

// CORRECT: Return-based syntax (modern Vue Router 4+)
router.beforeEach((to, from) => {
  if (!isAuthenticated) {
    return '/login'  // Redirect
  }
  // Return nothing (undefined) to proceed
})

// CORRECT: Return false to cancel navigation
router.beforeEach((to, from) => {
  if (hasUnsavedChanges) {
    return false  // Cancel navigation
  }
})

// CORRECT: Async with return-based syntax
router.beforeEach(async (to, from) => {
  const user = await fetchUser()
  if (!user) {
    return { name: 'Login', query: { redirect: to.fullPath } }
  }
  // Proceed with navigation
})

Return Values Explained

router.beforeEach((to, from) => {
  // Return nothing/undefined - allow navigation
  return

  // Return false - cancel navigation, stay on current route
  return false

  // Return string path - redirect to path
  return '/login'

  // Return route object - redirect with full control
  return { name: 'Login', query: { redirect: to.fullPath } }

  // Return Error - cancel and trigger router.onError()
  return new Error('Navigation cancelled')
})

If You Must Use next() (Legacy Code)

If maintaining legacy code that uses next(), follow these rules strictly:

// CORRECT: Exactly one next() call per code path
router.beforeEach((to, from, next) => {
  if (!isAuthenticated) {
    next('/login')
    return  // CRITICAL: Exit after calling next()
  }

  if (!hasPermission(to)) {
    next('/forbidden')
    return  // CRITICAL: Exit after calling next()
  }

  next()  // Only reached if all checks pass
})

Error Handling Pattern

router.beforeEach(async (to, from) => {
  try {
    await validateAccess(to)
    // Proceed
  } catch (error) {
    if (error.status === 401) {
      return '/login'
    }
    if (error.status === 403) {
      return '/forbidden'
    }
    // Log error and proceed anyway (or return false)
    console.error('Access validation failed:', error)
    return false
  }
})

Key Points

  1. Prefer return-based syntax - Cleaner, less error-prone, modern standard
  2. next() must be called exactly once - If using legacy syntax, ensure single call per path
  3. Always return/exit after redirect - Prevent multiple navigation actions
  4. Async guards work naturally - Just return the redirect route or nothing
  5. Test all code paths - Each branch must result in either return or next()

Reference

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill is a collection of educational documentation and best practices for using Vue Router 4. It contains no executable code, network operations, or sensitive data access, and is focused entirely on providing guidance for frontend development patterns.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    9 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at bc922e4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago
version
1.0.0
author
github.com/vuejs-ai
  • Vue
  • vue-router
  • navigation-guards
  • routing
  • lifecycle
  • spa

README badge

README badge for vuejs-ai/skills/vue-router-best-practices

Teaches Vue Router 4 navigation guards, route lifecycle handling, and common patterns like preventing infinite redirects and managing stale data across param changes. Covers gotchas like component cleanup on navigation and the deprecated next() function.

Generated from the current SKILL.md.

Does this skill cover Vue Router 4?
Yes. The skill is specific to Vue Router 4 patterns, navigation guards, route params, and component lifecycle interactions.
What are the main topics covered?
Navigation guards (async/await, infinite loops, deprecated next() function), route lifecycle issues (stale data, cleanup), and production SPA setup.
Does this address the problem of component data not updating when route params change?
Yes. The skill includes guidance on handling stale data when navigating between the same route with different params.
Does this cover how to access component instances in navigation guards?
Yes. It addresses the gotcha that `this` is not available in beforeRouteEnter guards and explains the workaround.
Does this skill help prevent infinite redirect loops?
Yes. It includes patterns for identifying and avoiding infinite navigation guard redirect loops.

Generated from the current SKILL.md. These answers refresh after source changes.