Vue Route Middleware

raw JSON →
1.0.7 verified Thu Apr 23 auth: no javascript

`vue-route-middleware` is a lightweight utility for Vue.js applications designed to streamline and enhance the management of route middleware logic within `vue-router`. It simplifies the definition and execution of complex global route guards, offering both inline function and chainable middleware arrays directly within route meta fields. The library is currently stable at version 1.0.7, with its last major release (v1.0.0) providing the core functionality, followed by minor updates. Its primary differentiator is the ability to define middleware either as direct functions, an array of functions for chaining, or as named functions referenced from an object passed to `VueRouteMiddleware()`, allowing for flexible application across different router guards like `beforeEach` and `afterEach`. It promotes clean, readable route configurations by abstracting complex guard logic, making it easier to manage permissions, tracking, and other route-specific concerns. It does not introduce breaking changes frequently, focusing on stability within the 1.x series.

error Navigation aborted with a different navigation. Or: Navigation failed because a redirect occurred.
cause Multiple `next()` calls or conflicting redirects were triggered within the middleware chain without properly halting subsequent middleware execution.
fix
Ensure that if a middleware performs a redirect (e.g., next({ name: 'Login' })), it immediately return false; to prevent other middlewares in the chain from executing and potentially causing further navigation actions.
error TypeError: Cannot read properties of undefined (reading 'meta') (or similar for missing middleware execution)
cause The `VueRouteMiddleware()` function was not correctly invoked on a `vue-router` guard (e.g., `router.beforeEach`), or named middlewares were not passed to it when using the advanced object-based configuration.
fix
Verify that router.beforeEach(VueRouteMiddleware()); or router.beforeEach(VueRouteMiddleware({ AuthMiddleware, PaymentMiddleware })); is present in your router setup, and that all named middlewares referenced in meta.middleware are included in the object passed to VueRouteMiddleware.
error ReferenceError: [YourMiddlewareName] is not defined
cause You are attempting to use a named middleware in your route's `meta.middleware` array (e.g., `meta: { middleware: ['AuthMiddleware'] }`), but `AuthMiddleware` was not imported into your router file or not passed to the `VueRouteMiddleware` factory function.
fix
Import AuthMiddleware from its respective file (e.g., import AuthMiddleware from './route/middleware/auth';) and then include it in the object passed to the VueRouteMiddleware initializer: router.beforeEach(VueRouteMiddleware({ AuthMiddleware }));
gotcha To halt the execution of subsequent middlewares in a chain, a middleware function must explicitly `return false`. If `false` is not returned, the chain will continue to execute, even if a redirect (`next({ name: '...' })`) has been triggered.
fix After calling `next()` for a redirect or error, add `return false;` at the end of your middleware function to prevent further middlewares in the array from running.
gotcha Compatibility with Vue Router versions: This library is designed for Vue 2 and Vue Router 3. For Vue 3 applications, which use Vue Router 4, the router guard API has changed. Direct compatibility is not guaranteed, and you may need to adapt your middleware logic or consider alternatives built specifically for the Vue 3 ecosystem.
fix Ensure your project is using Vue 2 and Vue Router 3. If migrating to Vue 3, carefully review the `vue-router` 4 documentation for `beforeEach` and `afterEach` guard changes, or seek a Vue 3 native middleware solution.
gotcha Middleware functions, especially those used with `beforeEach`, must always call `next()` (or `next(false)`, `next('/path')`, etc.) or explicitly `return false` if the chain should stop. Failure to do so will leave the navigation pending indefinitely, leading to a stuck user experience.
fix Always include `next()` at the end of your middleware function's successful path, and ensure `return false` is used when a redirect or halt is initiated via `next()`.
npm install vue-route-middleware
yarn add vue-route-middleware
pnpm add vue-route-middleware

This quickstart demonstrates how to integrate and use `vue-route-middleware` with `vue-router` in a basic Vue 2 application. It shows defining and chaining named middleware functions to protect a '/dashboard' route based on simulated authentication and payment status, applying them via `router.beforeEach`.

import Vue from 'vue';
import VueRouter from 'vue-router';
import VueRouteMiddleware from 'vue-route-middleware';

Vue.use(VueRouter);

// Simulate user login status and payment status
const fakeUser = {
  isLogged: () => localStorage.getItem('isLoggedIn') === 'true',
  madePayment: () => localStorage.getItem('hasPaid') === 'true'
};

// Define dummy components
const Dashboard = { template: '<div><h1>Dashboard</h1><p>Welcome, {{ isLoggedIn ? "User" : "Guest" }}!</p></div>' };
const Login = { template: '<div><h1>Login Page</h1><p>Set isLoggedIn=true in localStorage to proceed.</p></div>' };
const Payment = { template: '<div><h1>Payment Page</h1><p>Set hasPaid=true in localStorage to proceed.</p></div>' };
const Home = { template: '<div><h1>Home Page</h1><p>Navigate to /dashboard.</p></div>' };

// Define middleware functions
const AuthMiddleware = (to, from, next) => {
  console.log('Running AuthMiddleware...');
  if (!fakeUser.isLogged()) {
    next({ name: 'Login' }); // Redirect to login
    return false; // Crucial: stop middleware chain
  }
  next(); // Continue if authenticated
};

const PaymentMiddleware = (to, from, next) => {
  console.log('Running PaymentMiddleware...');
  if (!fakeUser.madePayment()) {
    next({ name: 'Payment' }); // Redirect to payment
    return false; // Crucial: stop middleware chain
  }
  next(); // Continue if payment made
};

const routes = [
  { path: '/', name: 'Home', component: Home },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: Dashboard,
    meta: {
      middleware: ['AuthMiddleware', 'PaymentMiddleware'] // Apply named middlewares
    }
  },
  { path: '/login', name: 'Login', component: Login },
  { path: '/payment', name: 'Payment', component: Payment }
];

const router = new VueRouter({
  mode: 'history',
  routes
});

// Initialize vue-route-middleware with named middlewares
router.beforeEach(VueRouteMiddleware({ AuthMiddleware, PaymentMiddleware }));

// Create and mount the Vue app (for a full runnable example)
// new Vue({
//   router,
//   template: `
//     <div id="app">
//       <router-link to="/">Home</router-link> |
//       <router-link to="/dashboard">Dashboard</router-link> |
//       <router-link to="/login">Login</router-link> |
//       <router-link to="/payment">Payment</router-link>
//       <hr>
//       <router-view></router-view>
//     </div>
//   `
// }).$mount('#app');

// To test, open your browser console and set:
// localStorage.setItem('isLoggedIn', 'true');
// localStorage.setItem('hasPaid', 'true');
// Then navigate to /dashboard.