Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nuxt Vuex Store Cookies Issue

Good time of the day!

After a few weeks of development of my project, i've decided to migrate from plain Vue to Nuxt.

Mainly because i need SSR, although i know that Google can execute JS presented on the page and therefore generate appropriate content for their search bot.

Another reason is a general workflow of the project development. I like idea with automatic instantiation of routes, store, etc.

I've faced, however, a pretty strange behavior of the application when it is running in the mode: universal instead of mode: spa. And i don't want to switch to mode: spa since then i lose the SSR i was migrating for in the first place.

I' have an account module in the store - account.js which is responsible for handling any operations related to the account management, such as login/logout, get profile of authenticated user, store the token obtained from the login request as well as the logic for handling the 2FA TOTP procedure.

In my legacy application, i was able to get the token from the cookies by just using the following bit of the code

import Cookies from 'js-cookie';

export const state = {
   user: null,
   token: Cookies.get('token')
}

And save token after the successful authentication by executing the following mutation:

[types.ACCOUNT_SAVE_TOKEN] (state, { token, remember }) {
    state.token = token;
    Cookies.set('token', token, {
      expires: 365,
      httpOnly: true
    });
}

But after migration to Nuxt.js, every time im loggin in, the token value in the state is getting populated, but no cookie is set, and after navigating to the other page inside the project (it is pwa, so no reloading, etc) token is reset back to null.

This issue however is gone if application is switched to the mode: spa from mode: universal and everything is working just fine.

I've read many issues on the github as well as done pretty big portion of crawling throught the websites which are trying to solve the same issue, though none of the suggestions are working for me.

I've even installed the cookie-universal-nuxt package from NPM which claims to be working with the SSR, but yet every time I'm trying to access this.$cookies.get('token') in the state, or anywhere else (mutations for example), I'm just getting error about using the method (get/set/remove) on null.

Does anyone know or have an idea on how to overcome this issue, at least if it is possible without going back to the mode: spa?

P.S. Running npm run build|generate yields same files as for the normal vue (without the content, just the structure until the target element is readched) while in mode: spa.

like image 343
Ivan Zhivolupov Avatar asked Jun 13 '18 23:06

Ivan Zhivolupov


People also ask

How does nuxt work with Vuex?

That's why Nuxt implements Vuex in its core. Nuxt will look for the store directory. If it contains a file, that isn't a hidden file or a README.md file, then the store will be activated. This means that Nuxt will:

How do I activate a store in nuxt?

Using a store to manage the state is important for every big application. That's why Nuxt implements Vuex in its core. Nuxt will look for the store directory. If it contains a file, that isn't a hidden file or a README.md file, then the store will be activated. This means that Nuxt will: Add the store option to the root Vue instance.

What is the Vuex store directory?

The store directory contains your Vuex Store files. The Vuex Store comes with Nuxt.js out of the box but is disabled by default. Creating an index.js file in this directory enables the store. This directory cannot be renamed without extra configuration. Using a store to manage the state is important for every big application.

When to use nuxtserverinit?

If the action nuxtServerInit is defined in the store and the mode is universal, Nuxt will call it with the context (only from the server-side). It's useful when we have some data on the server we want to give directly to the client-side.


1 Answers

Okay, after around 12 hours trying to wrap my head around this issue, i've decided to go the 'dirty' way and create middleware which is doing, in my opinion, way to much processing on each request.

import CookieParser from 'cookieparser';

export default async function ({ store, req }) {
  if (!store.getters['account/check']) {
    if (!store.state.account.token) {
      if (process.server) {
        let requestCookies = CookieParser.parse(req.headers.cookie);
        if (requestCookies.hasOwnProperty('token')) {
          store.dispatch('account/saveToken', {
            token: requestCookies.token,
            remember: true
          });
        }
      }
    }
    if (store.state.account.token) {
      if (!store.state.account.user) {
         try {
           await store.dispatch('account/fetchUser');
         } catch (error) { }
      }
    }
  }
  return Promise.resolve();
}
like image 89
Ivan Zhivolupov Avatar answered Oct 26 '22 23:10

Ivan Zhivolupov