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

Next.js v13中如何在'use client'组件中使用.env变量?

在Next.js v13中解决客户端Apollo组件访问.env变量的问题

你当前的Apollo包装组件标记了'use client',无法直接读取未加NEXT_PUBLIC_前缀的.env变量——这是Next.js的默认规则:只有带NEXT_PUBLIC_前缀的环境变量会被暴露给客户端代码。针对你的场景,有两种可行解决方法:

方案1:使用NEXT_PUBLIC_前缀的环境变量(适合非敏感配置)

如果你的GraphQL地址和访问令牌不需要保密(比如公开的客户端令牌),可以直接给.env变量添加NEXT_PUBLIC_前缀:

  1. 修改.env文件:
NEXT_PUBLIC_GRAPHQL_ENDPOINT=你的GraphQL服务地址
NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN=你的客户端访问令牌
  1. 更新组件中的变量读取逻辑:
'use client';

import { ApolloLink, HttpLink } from '@apollo/client';
import {
  ApolloNextAppProvider,
  NextSSRInMemoryCache,
  NextSSRApolloClient,
  SSRMultipartLink,
} from '@apollo/experimental-nextjs-app-support/ssr';

// 读取带NEXT_PUBLIC_前缀的变量
const { NEXT_PUBLIC_GRAPHQL_ENDPOINT, NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN } = process.env;

export function makeClient() {
  const httpLink = new HttpLink({
    uri: NEXT_PUBLIC_GRAPHQL_ENDPOINT,
    headers: {
      authorization: NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN ? `Bearer ${NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN}` : '',
    },
    fetchOptions: { cache: 'no-store' },
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === 'undefined'
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true,
            }),
            httpLink,
          ])
        : httpLink,
  });
}

export function ApolloWrapper({ children }: React.PropsWithChildren) {
  return <ApolloNextAppProvider makeClient={makeClient}>{children}</ApolloNextAppProvider>;
}

方案2:通过服务器组件传递配置(更安全,适合敏感令牌)

如果你的访问令牌是敏感信息(不能暴露给客户端),推荐用这种方法:利用服务器组件可以直接读取所有.env变量的特性,将配置作为props传递给客户端的ApolloWrapper。

  1. 修改ApolloWrapper组件,接收配置参数:
'use client';

import { ApolloLink, HttpLink } from '@apollo/client';
import {
  ApolloNextAppProvider,
  NextSSRInMemoryCache,
  NextSSRApolloClient,
  SSRMultipartLink,
} from '@apollo/experimental-nextjs-app-support/ssr';

// 定义配置类型
type ApolloConfig = {
  graphqlEndpoint: string;
  contentfulAccessToken: string;
};

// 让makeClient接收配置参数
export function makeClient(config: ApolloConfig) {
  const httpLink = new HttpLink({
    uri: config.graphqlEndpoint,
    headers: {
      authorization: config.contentfulAccessToken ? `Bearer ${config.contentfulAccessToken}` : '',
    },
    fetchOptions: { cache: 'no-store' },
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === 'undefined'
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true,
            }),
            httpLink,
          ])
        : httpLink,
  });
}

// ApolloWrapper接收config props
export function ApolloWrapper({ children, config }: React.PropsWithChildren<{ config: ApolloConfig }>) {
  return <ApolloNextAppProvider makeClient={() => makeClient(config)}>{children}</ApolloNextAppProvider>;
}
  1. 在服务器组件(比如app/layout.tsx)中引入ApolloWrapper并传递配置:
// layout.tsx 默认是服务器组件,无需标记'use client'
import { ApolloWrapper } from './apollo-wrapper';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  // 服务器组件可以直接读取所有.env变量
  const apolloConfig = {
    graphqlEndpoint: process.env.GRAPHQL_ENDPOINT!,
    contentfulAccessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
  };

  return (
    <html lang="en">
      <body>
        <ApolloWrapper config={apolloConfig}>{children}</ApolloWrapper>
      </body>
    </html>
  );
}

注意事项

  • 敏感令牌(如服务端专属的访问密钥)绝对不能使用方案1,否则会被打包到客户端代码中,造成安全风险。
  • 方案2中,Apollo的NextSSRApolloClient会自动处理SSR和客户端的状态同步,令牌只会在服务器请求和客户端内部请求中使用,不会暴露到浏览器的开发者工具中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:31:09