pinia-plugin-persistedstate icon indicating copy to clipboard operation
pinia-plugin-persistedstate copied to clipboard

[nuxt] Nuxt ssr cookie limit 4096bytes . Need a bigger alternative.

Open stephenjason89 opened this issue 3 years ago • 16 comments

Hello, are there other alternatives to cookie? I have a bigger store which needs to persist and it is more than 4096bytes

stephenjason89 avatar Jul 12 '22 19:07 stephenjason89

So far, i can only think of browser storages like localStorage, but it is client only. Do you need the SSR full compatibility ?

prazdevs avatar Jul 13 '22 07:07 prazdevs

@prazdevs yes, ssr full compatibility. I believe localstorage is higher and only client side. I'd be using it to store roles, permissions, tokens etc.. So i need it to be SSR compatible to be able to render pages server side customized to each role or depending on what permissions they have.

stephenjason89 avatar Jul 13 '22 09:07 stephenjason89

hello @prazdevs have you found anything that can help on this matter?

Thank you so much

stephenjason89 avatar Jul 19 '22 13:07 stephenjason89

I could only think of splitting the store into multiple cookies, cause i dont see many alternatives compatible with both client and server side 🤔

prazdevs avatar Jul 19 '22 23:07 prazdevs

@prazdevs I've tried splitting it to multiple cookies but it still does reach a limit. Higher though but still get's an error

stephenjason89 avatar Jul 20 '22 07:07 stephenjason89

I dont know what data structure you store in Pinia, but if you have unsplittable properties/chunks heavier than 4KB, I dont think they belong in the store. Maybe some cached database middleware or something would be more appropriate ?

prazdevs avatar Jul 20 '22 09:07 prazdevs

@stephenjason89 can you give more info about data you're storing. It's used for what purpose? I'm curious.

ASoldo avatar Jul 20 '22 09:07 ASoldo

@ASoldo After I login, i get back all this info and I am storing

    user:{
       id: 1
       name: stephenjason89
       branches:[{id:1, name:'warehouse']
       roles:[ {name: 'Admin', permissions: ['many', 'different' , 'permissions']} ]         -> this can be a lot specially if you are an admin
       permissions:['specific','user','permissions']        
    }
    token: 'Bearer token lkjalksjdlkjasldjlasdkajlsdjlajsdajsd',
    tokenExpiration: date,
    refreshToken: date,
    refreshTokenExpiration: 'Bearer token lkjalksjdlkjasldjlasdkajlsdjlajsdajsd',

This is so i don't need to query what permissions the user have.

I use it here because I need this info to customize the page being rendered in the server side depending on the users permissions

I reach the 4kb limit after having maybe 30 permissions

@prazdevs Would you mind giving me samples on some cached database middleware?

stephenjason89 avatar Jul 20 '22 10:07 stephenjason89

Any update on this thread. I am facing the same problem

FrancoLab avatar Sep 01 '22 12:09 FrancoLab

Ive been trying to play around alternative solutions that dont interfere with the plugin, but it's not very easy. Technically, cookies should not have a limited size (from the cookies RFC) but implementations decided otherwise. As stated earlier, I don't think such big objects belong in cookies anyways as they are conveyed by the requests.

Another "issue" is the state of nuxt that is not in stable release now and lacks documentation on that side, so it's not really helping me.

Finally I want to keep the plugin as framework-agnostic as possible, so anything in the core folder has 0 dependency. The nuxt helper is just to make things easier for the developer.

I'll keep on trying with recipes to make SSR cookies work whenever i get some time.

Anyone interested in trying to tackle this issue, feel free to do so, keep in mind that anything in the core plugin shouldnt be touched/altered.

prazdevs avatar Sep 01 '22 13:09 prazdevs

Thanks @prazdevs, is there a way to use the plugin to store multiple cookies. ie A cookie with a specific key per store that you set up. Mine does not even persist all my stores. Only one of them.

FrancoLab avatar Sep 01 '22 13:09 FrancoLab

Technically it should, but I need to look into when the cookie and keys are parsed and created, that could explain your problem.

prazdevs avatar Sep 01 '22 13:09 prazdevs

Maybe I did something wrong. How can I share my example?

FrancoLab avatar Sep 01 '22 13:09 FrancoLab

Here is my Nuxt3 Plugin:

// plugins/persistedstate.js
import { createNuxtPersistedState } from "pinia-plugin-persistedstate/nuxt";
import { useCookie } from "#app"; // optional import as Nuxt will auto-import it

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.$pinia.use(createNuxtPersistedState(useCookie));
});

My Store

import {defineStore} from 'pinia'
import axios from 'axios'

const baseUrl = url;

export const useGlobalConfigStore = defineStore('globalConfig', {
	state: () => ({
		config: null,
		fxRates: null,
		locales: null,
		error: null,
        count: 0,
        countGlobal: 0,
        countFx: 0,
        countLang: 0,
	}),
	actions: {
		async getConfig() {
            let header = {
                "Accept": "application/json",
                "Accept-Language": "en",
                Authorization: "Bearer token",
            }

			let reqOptions = {
				url: url,
				method: "GET",
				headers: header,
			}

			await axios
				.request(reqOptions)
				.then((response) => {
					if (response.status === 200) {
						this.config = response.data.result.data;
						this.error = null;
					} else {
						console.log({response});
					}
                    this.countGlobal = this.countGlobal + 1;
				})
				.catch((error) => {
					this.error = error;
				})

		},

		async getCurrencyConfig() {
            let header = {
                "Accept": "application/json",
                "Accept-Language": "en",
                Authorization: "Bearer token",
            }

			let reqOptions = {
				url: url,
				method: "GET",
				headers: header,
			}

			await axios
				.request(reqOptions)
				.then((response) => {
					if (response.status === 200) {
						this.fxRates = response.data.result.data;
						this.error = null;
					} else {
						console.log({response});
					}
                    this.countFx = this.countFx + 1;
				})
				.catch((error) => {
					this.error = error;
				})
		},

		async getLocaleConfig() {
            let header = {
                "Accept": "application/json",
                "Accept-Language": "en",
                Authorization: "Bearer token",
            }

			let reqOptions = {
				url: url,
				method: "GET",
				headers: header,
			}

			await axios
				.request(reqOptions)
				.then((response) => {
					if (response.status === 200) {
						this.locales = response.data.result.data;
						this.error = null;
					} else {
						console.log({response});
					}
                    this.countLang = this.countLang + 1;
				})
				.catch((error) => {
					this.error = error;
				})
		}
	},
	persist: {
        key: "globalStore",
    },
})

FrancoLab avatar Sep 01 '22 13:09 FrancoLab

The problem I am facing is that it only persists one of my stores. This one in the example above does not persist.

FrancoLab avatar Sep 01 '22 13:09 FrancoLab

You may want to open another issue with a proper reproduction repo/stackblitz to make it clearer, it's moving away from the main concern of this issue :)

prazdevs avatar Sep 01 '22 23:09 prazdevs

As the solution proposed in #99 works, you can use it to create your own storage deriving nuxt's useCookie (or any sort of cookie) and pass it to the plugin. Closing this issue as the split will not be implemented since out of scope, but it has a workaround.

prazdevs avatar Nov 13 '22 21:11 prazdevs