You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:45:33