Lesson 17 / 25
Navigation Guards and Lazy Routes
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.
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.
Quick check: What does returning false from a beforeEach guard do?
- Redirects to the home route
- Reloads the page
- Cancels the navigation
- Skips the remaining guards and continues
Answer
Cancels the navigation — Return a route location to redirect instead.