You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Nuxt has a useful plugin injection system that allows you to register instance properties on Vue.prototype, while still maintaining isolation by having it reference an underlying property on this.$root. I'd like this pattern to be documented here.
Background
I'm adding authentication to my Vue+Vuex+SSR app. The details of this aren't worth getting into, but the short version is that my app has an "auth token" that needs to get passed on every API request. During server-side rendering, the server would read the auth token out of a session cookie, and then set it in the Vuex store. On the client-side, the auth token would also be read out of this cookie and set locally.
I used to make API requests only inside Vuex actions, which made using this token relatively easy: it was in the Vuex context, and I just passed the context to an apiRequest() helper that wrapped Vuex.
However, I found myself also wanting to be able to make requests inside my components without going through Axios, and I got annoyed that I had to get the token out of the store every time. I started looking into other patterns for this, and found nuxt's axios module. This adds an $axios property to your Vue instance and stores.
I was surprised to see this module has a setToken() method allowing you to set an authentication token to use with all of your requests. My first thought was that this must have a security flaw - if $axios is registered on Vue.prototype, and $axios.setToken() updates the token for all $axios requests, wouldn't this mean that non-isolated server-side-rendered Vue instances could mutate the access token out from under each other, as the Avoiding Stateful Singletons section of the doc warns again?
I started investigating how Nuxt's "plugins" are implemented, and was impressed by their workaround for this: their inject method, as documented here and implemented here, uses the following technique (simplified here):
functioninjectProperty(appConfig,keyvalue){// pass the property to the root Vue instance's optionsappConfig[key]=value;Vue.use(()=>{if(!Vue.prototype.hasOwnProperty(key)){// register a Vue.prototype[key] getter that retrieves the value from the root options Object.defineProperty(Vue.prototype,key,{get(){returnthis.$root.$options[key];},});}});}functioncreateApp(){constappConfig={// ...};constaxiosInstance=axios.create({baseURL: `${process.env.API_URL}/api/`,});injectProperty(appConfig,'$axios',axiosInstance);constapp=newVue(appConfig);// ...}
I used this code for my $axios use case and it seems to work well at first glance. Of course, I did walk away from all this pondering whether I should just go ahead and port from my Webpack hodgepodge over to Nuxt, but at least I won't have to do it today.
Considering that Vue's general strategy for avoiding singletons (such as through singleton module imports) is "register it on the instance," having a pattern for safely registering to Vue.prototype seems worth documenting here in the SSR guide.
The text was updated successfully, but these errors were encountered:
Nuxt has a useful plugin injection system that allows you to register instance properties on
Vue.prototype
, while still maintaining isolation by having it reference an underlying property onthis.$root
. I'd like this pattern to be documented here.Background
I'm adding authentication to my Vue+Vuex+SSR app. The details of this aren't worth getting into, but the short version is that my app has an "auth token" that needs to get passed on every API request. During server-side rendering, the server would read the auth token out of a session cookie, and then set it in the Vuex store. On the client-side, the auth token would also be read out of this cookie and set locally.
I used to make API requests only inside Vuex actions, which made using this token relatively easy: it was in the Vuex context, and I just passed the context to an
apiRequest()
helper that wrapped Vuex.However, I found myself also wanting to be able to make requests inside my components without going through Axios, and I got annoyed that I had to get the token out of the store every time. I started looking into other patterns for this, and found nuxt's axios module. This adds an
$axios
property to your Vue instance and stores.I was surprised to see this module has a
setToken()
method allowing you to set an authentication token to use with all of your requests. My first thought was that this must have a security flaw - if$axios
is registered onVue.prototype
, and$axios.setToken()
updates the token for all$axios
requests, wouldn't this mean that non-isolated server-side-rendered Vue instances could mutate the access token out from under each other, as the Avoiding Stateful Singletons section of the doc warns again?I started investigating how Nuxt's "plugins" are implemented, and was impressed by their workaround for this: their
inject
method, as documented here and implemented here, uses the following technique (simplified here):I used this code for my
$axios
use case and it seems to work well at first glance. Of course, I did walk away from all this pondering whether I should just go ahead and port from my Webpack hodgepodge over to Nuxt, but at least I won't have to do it today.Considering that Vue's general strategy for avoiding singletons (such as through singleton module imports) is "register it on the instance," having a pattern for safely registering to
Vue.prototype
seems worth documenting here in the SSR guide.The text was updated successfully, but these errors were encountered: