Nuxt client-side middleware on direct page access

Problem

These days, I've been really enjoying the JAM stack, however, I'm noticing an issue with client-side middleware checks. On direct access or page refresh, the middleware runs checks against our vuex store. However, the vuex store has not been hydrated yet at this point, so it will return its default values (of null, in my case).

If we use the traditional approach as below, we will always return false, as the store.state object has not been hydrated at this point when accessing this route directly.

export default function ({ store, redirect }) {
  // If the user is not authenticated
  if (!store.state.authenticated) {
    return redirect('/login')
  }
}

Let's say our url is http://localhost:3000/admin where we only want authenticated users to access. If we go to / and then click a nuxt-router link to /admin, this middleware will run correctly.

If we log in, then open a new tab and access /admin directly, or refresh while on this url, our middleware will not work.

Solution

Solution may not be the best term, but work-around is probably a better description. I frequently use a persisted vuex store in local storage. I can write this logic manually, but I'm lazy and I typically use vuex-persistedstate.

This gives us a persisted mirror of our vuex store at any lifecycle. So, in the middleware, we can simply check against our localStorage object, instead of the vuex store from our context object.

export default function ({ redirect }) {
  // check against local storage object.
  const store = JSON.parse(localStorage.getItem('vuex'));
  
  // If the user is not authenticated
  if (!store.state.authenticated) {
    return redirect('/login')
  }
}

This will return the true current value of our authenticated user.

You do not need to use vuex-persistedstate to impliment this work-around, but you do need to persist whatever state you want available in your middleware in your local storage.

JAMstack is still a (relatively) new frontier, albiet with some really old school elements baked in, so decoupling the last 10 years of javascript bloat will come with some gotchas.

Enjoy!