Next.js 13.5:Script组件条件渲染与src条件赋值的差异原因咨询
问题场景
我正在使用Next.js 13.5,希望仅在生产环境中加载Google Recaptcha脚本。尝试了两种实现方式,第一种条件渲染<Script>组件不生效,第二种条件设置src属性却能正常工作,想了解两种写法的差异,以及该问题是否由Next.js框架导致。
第一种写法(不生效)
// _document.js, doesn't work const isProduction = process.env.NODE_ENV === "production"; const nonce = "1234-abcd-wxyz"; // ... <Html lang="en"> <Head nonce={nonce}> {isProduction && <Script async defer strategy="afterInteractive" src={`https://www.google.com/recaptcha/api.js?render=${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY || ""}`} />} </Head> </Html>
第二种写法(生效)
// _document.js, working const isProduction = process.env.NODE_ENV === "production"; const nonce = "1234-abcd-wxyz"; // ... <Html lang="en"> <Head nonce={nonce}> <Script async defer strategy="afterInteractive" src={isProduction ? `https://www.google.com/recaptcha/api.js?render=${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY || ""}` : ""} /> </Head> </Html>
问题解答
两种写法的核心差异
组件渲染逻辑与框架处理链路不同
- 第一种是条件渲染
<Script>组件本身:在_document.js的服务器端渲染(SSR)阶段,isProduction的判断会决定是否生成<Script>组件的渲染记录。但Next.js的<Script>组件在_document.js中不会直接输出为HTML标签,而是被框架收集后,在客户端 hydration 阶段统一处理加载逻辑。如果SSR阶段不渲染组件,客户端就没有对应的加载任务,自然无法加载脚本。 - 第二种是始终渲染组件,动态设置
src属性:<Script>组件会被框架正常收集,客户端 hydration 时会读取src的实际值。当isProduction为真时,src是有效的脚本地址,框架触发加载;为假时src为空,脚本不会加载,完全符合需求。
- 第一种是条件渲染
Next.js对
<Script>组件的封装特性
Next.js的<Script>是优化后的封装组件,和原生<script>标签的处理逻辑不同。它会根据指定的strategy控制加载时机,同时处理nonce、CSP等安全配置。在_document.js这类SSR入口文件中,组件的渲染结果不会直接写入HTML,而是由框架在客户端后续执行加载流程,这就导致条件渲染组件的方式无法传递加载指令到客户端。
是否由Next.js框架导致?
是的,这个差异完全由Next.js对<Script>组件的特殊处理逻辑导致。原生HTML中条件渲染<script>标签是可行的,但Next.js的<Script>组件依赖框架的客户端加载调度机制,而非直接的SSR输出。因此在_document.js中,条件渲染组件的方式无法触发脚本加载,而动态设置src的方式能让框架正常处理加载判断。
内容的提问来源于stack exchange,提问作者Aung Kaung Khant - Takao
相关产品推荐
相关产品推荐

