Nuxt 2如何禁止SSR模式执行fetch,仅客户端触发避免重复创建账号
解决Nuxt中Google OAuth重定向导致重复创建账号的问题
问题背景
Google OAuth重定向到mysite.com/register?code=foo后,Nuxt会分别在SSR和客户端模式下各加载一次页面,导致触发两次创建账号的请求。尝试用process.client判断限制执行时机,但未生效;同时使用@nuxtjs/composition-api的useFetch示例代码时持续报错。
尝试过的无效代码
if (code.value !== '' && process.client && !process.server) { fetch(process.env.baseUrl + 'login-with-google', { method: 'POST', body: JSON.stringify({ "code": code.value }) }) }
报错的useFetch示例代码:
<template> <div> <h1>Blog posts</h1> <template v-if="$fetchState.pending"> <content-placeholders> <content-placeholders-text :lines="20" /> </content-placeholders> </template> <template v-else-if="$fetchState.error"> <p>Error while fetching posts: {{ $fetchState.error.message }}</p> </template> <template v-else> <ul> <li v-for="post of posts" :key="post.id"> <n-link :to="`/posts/${post.id}`"> {{ post.title }} </n-link> </li> <li> <n-link to="/posts/404"> 404 post </n-link> </li> </ul> </template> </div> </template> <script> import { defineComponent, useFetch, useContext, ref, } from '@nuxtjs/composition-api' export default defineComponent({ setup() { const posts = ref(null) const { $http } = useContext() useFetch(async () => { posts.value = await $http .$get('https://jsonplaceholder.typicode.com/posts') .then(posts => posts.slice(0, 20)) }) return { posts } }, }) </script>
有效解决方案
方案1:Options API - 利用mounted钩子(仅客户端执行)
mounted生命周期钩子只会在客户端触发,完全避开SSR执行:
export default { mounted() { const code = this.$route.query.code if (code) { fetch(`${process.env.baseUrl}/login-with-google`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }) } } }
方案2:Composition API - 结合onMounted
使用onMounted确保代码仅在客户端执行,同时正确获取路由参数:
import { defineComponent, onMounted, useRoute } from '@nuxtjs/composition-api' export default defineComponent({ setup() { const route = useRoute() onMounted(() => { const code = route.value.query.code if (code) { fetch(`${process.env.baseUrl}/login-with-google`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }) } }) return {} } })
方案3:Composition API - 配置useFetch禁用SSR
如果需要使用useFetch,必须显式设置server: false参数,阻止SSR端执行:
import { defineComponent, useFetch, useRoute } from '@nuxtjs/composition-api' export default defineComponent({ setup() { const route = useRoute() useFetch(async () => { const code = route.value.query.code if (code) { await fetch(`${process.env.baseUrl}/login-with-google`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }) } }, { server: false }) // 核心配置:禁用SSR执行 return {} } })
额外优化:避免客户端重复执行
添加状态标记防止用户刷新页面时重复触发请求:
import { defineComponent, onMounted, useRoute, ref } from '@nuxtjs/composition-api' export default defineComponent({ setup() { const route = useRoute() const isCodeProcessed = ref(false) onMounted(() => { const code = route.value.query.code if (code && !isCodeProcessed.value) { isCodeProcessed.value = true fetch(`${process.env.baseUrl}/login-with-google`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }) } }) return {} } })
内容的提问来源于stack exchange,提问作者user19951168
相关产品推荐
相关产品推荐

