# Navigation Guards and Lazy Routes — Vue.js

Source: https://www.skillbyai.com/en/vue/rt-guards

> Controlling and splitting navigation.

## Guards and code splitting

**Navigation guards** run before a navigation is confirmed. A global `router.beforeEach((to, from) => ...)` can return `false` to cancel, a route location (such as `{ name: 'login' }`) to redirect, or nothing / `true` to continue; it can also be async. Per-route `beforeEnter` and in-component guards like `onBeforeRouteLeave` (useful for unsaved-changes prompts) also exist. **Lazy-loaded routes** use `component: () => import('./views/Settings.vue')`, so the bundler splits each page into its own chunk that is downloaded only when the route is first visited. Older code passes a third `next` argument; returning a value is the current recommended style.

## A global guard and lazy routes

Redirect and split chunks.

```javascript
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: () => import('@/views/HomePage.vue') },
    { path: '/login', name: 'login', component: () => import('@/views/LoginPage.vue') },
    { path: '/settings', component: () => import('@/views/SettingsPage.vue') },
  ],
})

router.beforeEach(async (to) => {
  if (to.path === '/settings' && !(await isLoggedIn())) {
    return { name: 'login', query: { redirect: to.fullPath } }
  }
  // returning nothing allows the navigation
})

// Inside a component's <script setup>:
// import { onBeforeRouteLeave } from 'vue-router'
// onBeforeRouteLeave(() => {
//   if (hasUnsavedChanges.value) return window.confirm('Discard changes?')
// })
```

## Guards are not security

Client-side guards improve the user experience, but anyone can bypass browser code. The API must still check authentication and authorisation on every request.

**Quiz:** What does returning false from a beforeEach guard do?

- [ ] Redirects to the home route
- [ ] Reloads the page
- [x] Cancels the navigation
- [ ] Skips the remaining guards and continues

*Answer:* Cancels the navigation. Return a route location to redirect instead.
