Exploring the Functionality of Using Multiple Middlewares in Vue.js 3

For my web app project using vue.js 3 and vue-router, I followed a helpful tutorial on implementing middleware pipelines. The tutorial can be found at: https://blog.logrocket.com/vue-middleware-pipelines/. This tutorial demonstrated creating middleware to prevent unauthorized access, as well as using multiple middleware for a single route structure like this:

children: [{
                path: '/dashboard/movies',
                name: 'dashboard.movies',
                component: Movies,
                meta: {
                    middleware: [
                        auth,
                        isSubscribed
                    ]
                }
            }],

In the tutorial, each middleware function calls the "next()" function once, but what if you need to call it multiple times for different purposes? Vue.js 3 documentation suggests using the "next()" function only once. How can we effectively implement multiple middlewares in vue.js 3 similar to the approach shown in the aforementioned tutorial?

Answer №1

If you're facing challenges with implementing middlewares in Vue3, here is an approach that might help:

// authentication middleware
import { useAuthStore } from "@/stores/auth";

export default async function auth({ next }) {
  const authStore = useAuthStore();
  
  const user = await authStore.checkAuth();

  if (!('id' in user)) {
    console.log("Not logged in");
    return next({
      name: "Login",
    });
  }
  return next();
}

Another middleware example:

// city selection middleware
import { useCitiesStore } from "@/stores/cities";

export default function hasCity({ next }) {
  const citiesStore = useCitiesStore()

  if (!citiesStore.city) {
    console.log('City not selected')
    return next({
      name: 'CitySelector'
    })
  }
  return next();
}

Incorporating the middlewares within the router:

import auth from '@/middlewares/auth'
import hasCity from '@/middlewares/hasCity'

// other imports and code

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      layout: 'default',
      middleware: [auth, hasCity]
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: Login,
    meta: {
      layout: 'blank'
    }
  },
  {
    path: '/city-selector',
    name: 'CitySelector',
    component: CitySelector,
    meta: {
      layout: 'blank'
    }
  }
];

const router = createRouter({
  routes,
});

function nextFactory(context, middleware, index) {
  const nextMiddleware = middleware[index];
  
  if (!nextMiddleware){
    return context.next;
  }
  const subsequentMiddleware = nextFactory(context, middleware, index + 1);
  return nextMiddleware({ ...context, next: subsequentMiddleware })
}

router.beforeEach((to, from, next) => {
  if(!to.meta.middleware){
    return next();
  }

  const middleware = Array.isArray(to.meta.middleware)
    ? to.meta.middleware
    : [to.meta.middleware];
  const context = {
    to,
    from,
    next,
    router,
  };

  return middleware[0]({ ...context, next: nextFactory(context, middleware, 1) });

});

export default router;

Answer №2

If you're looking for a seamless implementation without the need for configuration, consider using vue-middleware.

Check it out on Github: https://github.com/themustafaomar/vue-middleware

Explore the documentation here:

Here's an example of how it can be used:

{
  name: 'dashboard',
  path: '/dashboard',
  component: () => import('@/layouts/dashboard.vue'),
  meta: {
    middleware: 'dashboard',
    // or using array syntax..
    middleware: ['dashboard', 'logger'],
  },
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Incorporating Card Layouts with SwiperJS

Reference Code: See Example on Code Sandbox I am looking to implement a swiper that allows for navigating one slide at a time with a layout where slidesPerView: "auto" and fixed width are used. The first two slides behave as expected, but the la ...

How come I am receiving a null value for isMatch from bcrypt compare even though the two password strings match exactly?

Currently, I am attempting to authenticate a user based on a password. My approach involves using bcrypt compare to check if the user's requested password matches one stored in a MongoDB database. Despite the passwords being identical, I keep receivin ...

Running JavaScript code without blocking the main thread

While studying JavaScript and JSON, I encountered some issues. I have a script that functions with JSON data, but the performance of my code is not optimal. The code only works when I debug it step by step using tools like Firebug which leads me to conclud ...

resolving conflicts between Rails and JavaScript assets

Currently, I am facing an issue with two gems that provide JavaScript assets as they are conflicting with each other. The conflicting gems in question are the lazy_high_charts gem and the bootstrap-wysihtml5-rails gem. Initially, I only had the bootstrap ...

Select information from an array and store it within an object

I want to extract all objects from an array and combine them into a single object. Here is the current array data: userData = [ {"key":"firstName","checked":true}, {"key":"lastName","checked":true ...

Start CSS3 Animation Automatically

I am working on a multi-page website with a slider that includes a CSS3 animation featuring the famous rocket animation. Here is the code snippet I used: #outerspace { position: relative; height: 400px; background: #fff; color: #fff; } di ...

Is it possible to initially design a login page using HTML/CSS and JavaScript, and then integrate VUE into it?

As part of a school project, I am tasked with developing a web-based application for a library system. The goal is to create a platform where librarians can login and manage books by adding, removing, or editing them. My responsibility lies in handling the ...

Encountered an issue with accessing the property 'path' of undefined in nodejs

Below is my server side code snippet: var fs = require('fs'), MongoClient = require('mongodb').MongoClient, db; var url = "mongodb://localhost:27017/fullwardrobedb"; MongoClient.connect(url, {native_parser: true}, function (err, connec ...

What is the best way to remove specific items from an AngularJS ng-repeat loop?

Is there a way to filter out certain items in an ng-repeat loop? For instance, consider the following simplified code snippet: <div class="row" data-ng-repeat="entry in data.feed.entry | orderBy:'gsx$timestamp.$t':true"> {{entry.gsx$jobID ...

Access the value of a submitted form using jQuery, when there are multiple forms with identical class names

I've looked for a solution here but couldn't find one that meets my needs. I have multiple forms with the class name .sbt-form: <form class='sbt-form'> <input name='kord' val=1/> </form> <form class= ...

What is the best approach for creating a test that can simulate and manage errors during JSON parsing in a Node.js

My approach to testing involves retrieving JSON data from a file and parsing it in my test.js file. The code snippet below demonstrates how I achieve this: var data; before(function(done) { data = JSON.parse(fs.readFileSync(process.cwd() + '/p ...

Storing input field values in JavaScript using the onchange event handler.Would you like a different revision

I am looking to calculate the area by multiplying width and height entered into input fields, and then display the result. Any guidance would be greatly appreciated. Thank you! Here is my current code. const width = document.querySelector("#width"); con ...

Error: JSON parsing failed due to an unexpected token "u" at the beginning of the JSON string. This occurred in an anonymous function when

Implementing reCaptcha in my firebase project has been successful. I am now sending form data and the captcha response using grecaptcha.getResponse() to my server upon clicking the send button. Below is the code snippet from client.js: $('.sendUrl ...

What is the process for storing a particular model in a designated collection within MongoDB's database?

I am working with three different models: user, teacher, student. All of these are stored in the database under the users collection. However, I want to save the student model in its own separate collection called students, instead of mixing it with the us ...

Issues with incorrect source path in Typescript, Gulp, and Sourcemaps configuration

In my nodejs app, the folder structure is as follows: project |-- src/ | |-- controllers/ | | |`-- authorize-controller.ts | |`-- index.ts |--dist/ | |--controllers/ | | |`-- authorize-controller.js | | |`-- authorize-controller.js.map | ...

"Error message: Attempting to access state in getter without it being defined (Vu

Trying to access the status of a stored login session in my Vuex store, I encountered the following error: Uncaught TypeError: Cannot read property 'user' of undefined The Vuex store configuration is as follows: let store = { state ...

Issue encountered while attempting to utilize setStart and setEnd functions on Range object: Unhandled IndexSizeError: Unable to execute 'setEnd' on 'Range'

Every time I attempt to utilize a range, an error message appears in the console: Uncaught IndexSizeError: Failed to execute 'setEnd' on 'Range': The offset 2 is larger than or equal to the node's length (0). This is the script I ...

Populate the auto complete input box with items from a JSON encoded array

I have a PHP file that returns a JSON encoded array. I want to display the items from this JSON array in an autocomplete search box. In my search3.php file, I have the following code: <?php include 'db_connect.php'; $link = mysqli_connect($ho ...

AngularJS: monitoring changes in an array property

For the problem at hand, take a look at this link: http://plnkr.co/edit/ZphAKvZeoVtuGFSEmOKg?p=preview Imagine you have an array structured like this: var arr = [ { 'a': "123", 'b': "654" }, { 'a': "456", &apo ...

Issue with Date Picker not properly storing selected date in MySQL database

My goal is to save the datepicker date to MySQL by selecting the date format using JavaScript. I have verified that the date format appears correct as YYYY-MM-DD when logging to the console. However, when I try to execute an INSERT query to MySQL, the date ...