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

使用Cypress测试Remix应用时遇Hydration失败问题求助

Cypress测试Remix应用触发Hydration失败错误

问题描述

首次使用Cypress测试Remix应用时,所有页面均出现Hydration失败错误,该错误仅在Cypress环境下触发,非Cypress环境无此问题。

错误信息:
Error: Hydration failed because the initial UI does not match what was rendered on the server.

Cypress配置

import { defineConfig } from "cypress"

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      const isDev = config.watchForFileChanges
      const port = process.env.PORT ?? (isDev ? "3000" : "8811")
      const configOverrides: Partial<Cypress.PluginConfigOptions> = {
        baseUrl: `http://localhost:${port}`,
        video: !process.env.CI,
        screenshotOnRunFailure: !process.env.CI,
      }

      on("task", {
        log: (message) => {
          console.log(message)
          return null
        },
      })

      return { ...config, ...configOverrides }
    },
  },
})

测试用例示例(所有用例均报错)

describe("Wizard", () => {
  beforeEach(() => {
    cy.visit("/wizard")
  })

  it("goes through wizard", () => {
    cy.findByRole("button", { name: /U17/i }).click()
  })
})

错误截图

截图显示React Hydration失败的核心报错提示:Hydration failed because the initial UI does not match what was rendered on the server。


解决方案

1. 禁用Cypress实验性Session特性

Cypress的experimentalSessionAndOrigin特性可能干扰SSR的UI一致性,在配置中关闭该选项:

export default defineConfig({
  e2e: {
    experimentalSessionAndOrigin: false, // 禁用该实验特性
    setupNodeEvents(on, config) {
      // 保留原配置逻辑
    },
  },
})

2. 等待客户端Hydration完成

在访问页面后,等待客户端完成Hydration再执行测试操作,可通过检查自定义标识或等待元素稳定:

beforeEach(() => {
  cy.visit("/wizard")
  // 假设应用在Hydration完成后会设置window.hydrated为true
  cy.window().should("have.property", "hydrated", true)
  // 或者等待仅客户端渲染的元素出现
  // cy.get("[data-client-only]").should("be.visible")
})

3. 统一User-Agent

Cypress默认UA可能导致服务端渲染出不同UI,设置与普通浏览器一致的UA:

beforeEach(() => {
  cy.visit("/wizard", {
    headers: {
      "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }
  })
})

4. 测试环境临时禁用SSR

若以上方法无效,可在测试环境关闭Remix的SSR,确认问题根源:
在Remix的root.tsx中添加条件判断:

import { useLoaderData } from "@remix-run/react"

export function loader() {
  if (process.env.NODE_ENV === "test") {
    return { disableSSR: true }
  }
  // 原loader逻辑
}

export default function App() {
  const data = useLoaderData()
  if (data?.disableSSR) {
    return (
      <div suppressHydrationWarning>
        {/* 应用根组件 */}
      </div>
    )
  }
  // 原渲染逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:25:14