Next.js中引入Cookiebot脚本引发Hydration Error问题求助
问题根源
Cookiebot脚本会在客户端动态插入<noscript>元素,但服务端渲染的初始HTML中不存在该元素,导致客户端水合阶段DOM结构不匹配,触发报错。另外,未完成同意/拒绝操作就刷新页面时,Cookiebot可能留存未完成的状态,既会导致横幅不再渲染,也会加剧水合冲突。生产环境下Next.js的优化策略(如更严格的HTML校验或脚本加载时机调整)掩盖了这个问题,但开发环境会直接暴露。
解决方案
方案1:用Next.js官方next/script组件加载脚本
next/script专为Next.js的SSR/SSG场景优化脚本加载,能从根源避免水合不匹配:
'use client' import Script from 'next/script' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html> <head> <Script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" data-cbid="COOKIEBOT_ID" strategy="lazyOnload" /> {/* 其他head内容 */} </head> <body>{children}</body> </html> ) }
选择lazyOnload策略可确保脚本在页面加载完成后执行,避免干扰初始渲染和水合。若需更早加载,也可使用afterInteractive策略,但lazyOnload的水合兼容性最优。
方案2:在useEffect中动态插入脚本
通过useEffect确保脚本仅在客户端加载,彻底避开服务端渲染的DOM不匹配问题:
'use client' import { useEffect } from 'react' export default function RootLayout({ children }: { children: React.ReactNode }) { useEffect(() => { const script = document.createElement('script') script.id = 'Cookiebot' script.src = 'https://consent.cookiebot.com/uc.js' script.setAttribute('data-cbid', 'COOKIEBOT_ID') script.async = true document.head.appendChild(script) return () => { document.head.removeChild(script) } }, []) return ( <html> <head> {/* 其他head内容 */} </head> <body>{children}</body> </html> ) }
方案3:重置Cookiebot状态(可选)
若刷新后横幅仍不显示,可在脚本加载后强制重置状态,确保未操作时重新渲染横幅:
'use client' import { useEffect } from 'react' export default function RootLayout({ children }: { children: React.ReactNode }) { useEffect(() => { const loadCookiebot = () => { const script = document.createElement('script') script.id = 'Cookiebot' script.src = 'https://consent.cookiebot.com/uc.js' script.setAttribute('data-cbid', 'COOKIEBOT_ID') script.async = true script.onload = () => { if (window.Cookiebot) { window.Cookiebot.renew() } } document.head.appendChild(script) } loadCookiebot() return () => { const script = document.getElementById('Cookiebot') if (script) document.head.removeChild(script) } }, []) return ( <html> <head> {/* 其他head内容 */} </head> <body>{children}</body> </html> ) }
window.Cookiebot.renew()会重置Cookiebot状态,强制重新检查用户授权,确保未操作的刷新后横幅正常显示。
效果验证
修改后在开发环境刷新页面(未点击同意/拒绝),水合错误应消失,Cookiebot横幅能正常渲染。生产环境不受影响,依然保持原有工作状态。
内容的提问来源于stack exchange,提问作者user23455176
相关产品推荐
相关产品推荐

