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

Next.js getServerSideProps报window未定义 如何持久化存储payload

报错根因

getServerSideProps 是Next.js框架中仅在服务端Node.js环境运行的逻辑,执行阶段没有浏览器提供的window全局对象,直接在这个函数里调用window.localStorage必然触发ReferenceError: window is not defined。

可行解决方案

方案1:通过props透传数据,在客户端生命周期写入localStorage

这是改动最小、最符合Next.js执行逻辑的方案:

  1. 移除getServerSideProps中直接调用storePersistence的服务端存储逻辑,把需要持久化的payload序列化后加入返回的props中,传递给前端页面组件。
  2. 在页面组件内使用useEffect钩子执行存储逻辑——useEffect内的代码只会在浏览器端hydration完成后执行,可正常访问window对象。

修改后的getServerSideProps代码:

//@ts-ignore
export async function getServerSideProps({ req, res, query }) {
  const { id } = query
  const cookies = Cookies(req, res)
  const jwt = cookies.get('lit-auth')
  if (!jwt) {
    return {
      props: {
        authorized: false,
        persistencePayload: null
      },
    }
  }

  const { verified, payload } = LitJsSdk.verifyJwt({ jwt })
  if (
    payload.baseUrl !== "http://localhost:3000"
    || payload.path !== '/protected'
    || payload.extraData !== id
  ) {
    return {
      props: {
        authorized: false,
        persistencePayload: null
      },
    }
  }

  return {
    props: {
      authorized: !!verified,
      // 序列化后传递,避免服务端到客户端的序列化异常
      persistencePayload: verified ? JSON.stringify(payload) : null
    },
  }
}

页面组件内添加客户端存储逻辑:

import { useEffect } from 'react'
import type { InferGetServerSidePropsType } from 'next'

export default function ProtectedPage({
  authorized,
  persistencePayload
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
  // 仅在客户端执行存储
  useEffect(() => {
    if (persistencePayload) {
      window.localStorage.setItem('lit_protocols_jwt', persistencePayload)
    }
  }, [persistencePayload])

  // 原有页面渲染逻辑
  return <div>{authorized ? '已授权' : '未授权'}</div>
}

方案2:直接通过Set-Cookie写入浏览器持久化(更推荐鉴权场景使用)

你当前代码已经在服务端操作Cookie,完全可以直接在服务端校验通过后,把payload写入响应Cookie,浏览器收到响应后会自动持久化存储,不需要额外写客户端JS逻辑:

// 在校验通过的位置直接调用cookies.set即可,不需要访问window
cookies.set('lit_protocols_jwt', JSON.stringify(payload), {
  path: '/',
  // 7天过期,可按需调整
  expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  // 如果需要前端JS读取Cookie就设为false,仅服务端读取设为true可防XSS窃取,安全性更高
  httpOnly: false
})

注意:鉴权类敏感数据优先选择Cookie+httpOnly配置,安全性远高于localStorage。

方案选型参考
  • 如果存储的数据仅在前端业务逻辑中使用、不需要随请求自动上报,选方案1(localStorage),存储容量更大,不会额外增加请求体积。
  • 如果存储的是鉴权凭证、需要后续请求自动携带,选方案2(Cookie),实现更简单,安全配置更灵活。

内容的提问来源于stack exchange,提问作者NextNightFlyer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 05:45:38