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

在NextJS中无需props或context向React组件添加script标签的方案

可行解决方案

针对你在SSR模式NextJS(Pages Router)中注入script且避免相关内容进入NEXT_DATA的需求,可按实际场景选择以下方案:

方案1:直接在_document.tsx服务端获取并注入script(推荐需要首屏存在script的场景)

_document.tsx的逻辑仅在服务端运行,其中返回的属性仅用于服务端渲染HTML模板,不会被序列化到客户端的NEXT_DATA中,完全符合你的需求。
示例代码:

// pages/_document.tsx
import { Html, Head, Main, NextScript, DocumentContext } from 'next/document'

type DocumentProps = {
  externalScriptUrl: string
}

export default function Document({ externalScriptUrl }: DocumentProps) {
  return (
    <Html lang="zh-CN">
      <Head>
        {/* 直接注入script,可按需添加async/defer属性 */}
        <script src={externalScriptUrl} async />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Document.getInitialProps = async (ctx: DocumentContext) => {
  const initialProps = await Document.defaultGetInitialProps(ctx)
  // 服务端直接调用API获取script相关配置,该逻辑完全不会暴露到客户端
  const apiRes = await fetch('你的业务API地址,用于获取script地址/内容')
  const { scriptUrl } = await apiRes.json()
  return { ...initialProps, externalScriptUrl: scriptUrl }
}

方案2:客户端动态加载script(适合不需要首屏就加载的script)

所有逻辑在客户端侧执行,服务端完全不处理相关数据,自然不会有内容进入NEXT_DATA。你之前使用window失败大概率是因为在SSR阶段直接调用了客户端API,将逻辑放入useEffect即可规避这个问题。
示例代码:

// 任意需要引入script的组件内
import { useEffect } from 'react'

const YourComponent = () => {
  useEffect(() => {
    const loadThirdScript = async () => {
      // 客户端侧请求获取script配置,或直接硬编码地址
      const res = await fetch('你的业务API地址')
      const { scriptUrl } = await res.json()
      // 动态创建script标签
      const script = document.createElement('script')
      script.src = scriptUrl
      script.async = true
      // 可按需添加加载成功/失败回调
      script.onload = () => console.log('第三方库加载完成')
      script.onerror = () => console.error('第三方库加载失败')
      document.head.appendChild(script)
    }
    loadThirdScript()
  }, [])

  return <div>你的组件内容</div>
}
export default YourComponent

也可以直接用NextJS官方提供的next/script组件,比手动创建性能更优:

import Script from 'next/script'
import { useState, useEffect } from 'react'

const YourComponent = () => {
  const [scriptUrl, setScriptUrl] = useState('')
  useEffect(() => {
    const getScriptUrl = async () => {
      const res = await fetch('你的业务API地址')
      const { scriptUrl } = await res.json()
      setScriptUrl(scriptUrl)
    }
    getScriptUrl()
  }, [])

  return (
    <>
      {scriptUrl && <Script src={scriptUrl} strategy="afterInteractive" />}
      <div>你的组件内容</div>
    </>
  )
}

注意事项

  • 如果使用_document.tsx方案,不要在getInitialProps中返回不必要的敏感数据,所有返回值仅会用于渲染静态HTML,不会进入客户端上下文。
  • 如果你的项目已经升级到NextJS 13+ App Router,直接在根服务端布局组件中请求script配置并渲染script标签即可,服务端组件的所有数据处理逻辑都不会暴露到客户端,也不会生成NEXT_DATA相关内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 03:57:05