I want to do login auth in ___spa___ mode by adding a 'beforeEach' hook of vue-router, and I have not found any description about the hook of vue-router in the doc of nuxt. Is there any way to customize the 'beforeEach' hook of vue-router?
The code works in a webpack template is like this:
import Router from 'vue-router'
const router = new Router({
// ...
})
router.beforeEach((to, from, next) => {
if(!localStorage.getItem('userId')) {
next('/login');
} else {
next();
}
}
new Vue({
el: '#app',
router,
render: h => h(App)
}).$mount('#app')
I think you can use a plugin to hook into the root vue instance, grab the router and set the beforeEach method. https://nuxtjs.org/guide/plugins#inject-in-root-amp-context
@vuchl answer is correct.
Also, you can use middleware to achieve this and add the middleware into nuxt.config.js so it can be run for all pages.
@vuchl @Atinux Thanks!
@Atinux Excecpt it actually does not run for each pages. Since middlewares won't run on the client on first load while router.beforeEach will. So middlewares are not exactly for the same usage.
@Elfayer It depends if you use spa mode or universal.
@Atinux Interesting. Seems like you're right adding mode: 'spa' to my nuxt.config.js is calling the middleware on first load. Now a question comes to mind, why it doesn't under universal mode in the first place?
Here is an example to challenge you, I need to execute some code on each routing(including first load) on the client side. The reason is that I need to access the localStorage/sessionStorage/cookies. The server cannot access this. Maybe I am thinking of this the wrong way. The question is: How do I run code before each page is rendered on the client side? Basically an equivalent to router.beforeEach, which I thought middlewares are, I want to use the nuxt way.
@Elfayer Actually the fact that middleware are not run on client-side on first load is intentional: to avoid mismatch between server-side and client-side rendering.
If you need to store a session, you need to store it into a cookie that you can access from the server-side directly and populate your state, so when you render from the server, you can give the correct page to your user.
There is one way to execute code on client-side (only on first render) before mounting the app:
nuxt.config.js
module.exports = {
plugins: [
{ src: '~/plugins/hello.js', ssr: false }
]
}
plugins/hello.js
// Export a method to access the context
export default async (context) => {
window.alert('I am called before mounting the App on client-side')
// this method can be asynchronous too
}
But if you are using the store.state to display some content on your page and you change it here, you will have a Vue warning telling you that your server-side generated code does not match with your client-side generated code.
See https://mountain-mole.glitch.me/ for a demo (code: https://glitch.com/edit/#!/mountain-mole). As you can see, this is a terrible User experience and it's why we don't recommend to do this.
@Atinux Hi, tried what you suggested but context.redirect doesn't work inside a plugin.
I suppose that the router hasn't initiated yet, Do you have any workaround?
Thanks!
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
@Elfayer Actually the fact that middleware are not run on client-side on first load is intentional: to avoid mismatch between server-side and client-side rendering.
If you need to store a session, you need to store it into a cookie that you can access from the
server-sidedirectly and populate your state, so when you render from the server, you can give the correct page to your user.There is one way to execute code on client-side (only on first render) before mounting the app:
nuxt.config.jsplugins/hello.jsBut if you are using the
store.stateto display some content on your page and you change it here, you will have a Vue warning telling you that your server-side generated code does not match with your client-side generated code.See https://mountain-mole.glitch.me/ for a demo (code: https://glitch.com/edit/#!/mountain-mole). As you can see, this is a terrible User experience and it's why we don't recommend to do this.