Next.js SSR项目Apollo Client运行时读取环境变量适配CI/CD问题
问题原因
你遇到的报错是因为App组件顶层直接调用useApollo初始化Apollo Client,Next.js在构建阶段执行预渲染逻辑时会运行这段初始化代码,而此时你没有传入GRAPHQL_URL环境变量,导致读取publicRuntimeConfig.GRAPHQL_URL返回undefined。其他使用publicRuntimeConfig的代码没有问题,是因为它们都在运行时的请求处理阶段(如getServerSideProps、getInitialProps或客户端交互阶段)才读取配置,不会在构建阶段触发。
以下是三种可落地的解决方案,均能满足同一份构建产物多环境部署的需求:
方案1:加兜底值避免构建报错
构建阶段的预渲染不会实际发起GraphQL请求,你只需要给uri加一个临时兜底值即可,运行时启动服务传入的环境变量会自动生效:
- 首先确认你在Apollo初始化文件顶部正确导入了Next.js配置:
import getConfig from 'next/config'; const { publicRuntimeConfig } = getConfig();
- 修改createApolloClient的uri配置:
return new ApolloClient({ // 其余配置保持不变 link: createHttpLink({ uri: publicRuntimeConfig.GRAPHQL_URL || 'http://placeholder-graphql-url', credentials: 'same-origin', headers: httpLinkHeaders }) });
方案2:使用动态Link(更稳妥)
调整Apollo Link逻辑,每次发起请求时才实时读取配置,彻底避免初始化阶段的取值问题:
import { setContext } from '@apollo/client/link/context'; const createApolloClient = (authToken: string | null) => { // 动态读取配置的上下文链路 const dynamicConfigLink = setContext((_, { headers }) => { const { publicRuntimeConfig } = getConfig(); return { uri: publicRuntimeConfig.GRAPHQL_URL, headers: { ...headers, ...(authToken && { Authorization: `Bearer ${authToken}` }) } }; }); const baseHttpLink = createHttpLink({ credentials: 'same-origin' }); return new ApolloClient({ name: 'client', ssrMode: typeof window === 'undefined', link: dynamicConfigLink.concat(baseHttpLink), cache: new InMemoryCache() }); };
方案3:构建阶段传入临时环境变量
如果不想修改业务代码,可在CI构建步骤临时传入一个任意值的GRAPHQL_URL,该值不会被写死到构建产物中,运行时启动服务传入的变量会覆盖它:
GRAPHQL_URL=http://temp-graphql-url yarn build
内容的提问来源于stack exchange,提问作者Anders Kitson
相关产品推荐
相关产品推荐

