Next.js中如何在_app文件中安全隐藏并使用环境变量?
客户端安全使用环境变量的方案
一、核心原则先明确
- 任何直接暴露给客户端的环境变量,最终都会被打包进前端代码,不存在客户端层面的保密可能。真正需要保密的密钥、API密钥等敏感信息,必须只在服务端(比如
getServerSideProps、API路由、Server Components)中使用。 _app.js无法使用getServerSideProps,但可以通过其他方式传递服务端处理后的安全数据,或合理区分环境变量的使用场景。
二、具体实现方案
1. 区分环境变量类型
- 服务端专用变量:无需前缀(比如
SECRET_API_KEY),这类变量只会在服务端代码加载,永远不会暴露给客户端。 - 客户端可访问变量:必须添加
NEXT_PUBLIC_前缀(比如NEXT_PUBLIC_API_BASE_URL),构建时会注入客户端代码,适合存放非敏感配置(如公开API地址、第三方公开ID)。
2. 给客户端传递服务端处理后的安全数据
如果业务需要将服务端处理后的非敏感数据(而非原始密钥)传给客户端,比如用户授权令牌,可通过两种方式实现:
- 页面
getServerSideProps传递数据:每个页面的getServerSideProps可在服务端获取数据后,通过props传递给页面,_app.js能通过pageProps拿到这些数据。
示例代码:// pages/some-page.js export async function getServerSideProps(context) { // 服务端访问保密环境变量 const secretKey = process.env.SECRET_API_KEY; // 用密钥请求数据,返回非敏感结果(如用户信息) const userData = await fetch(`https://api.example.com/user`, { headers: { Authorization: `Bearer ${secretKey}` } }).then(res => res.json()); return { props: { userData } }; } // 页面组件接收props,_app可通过pageProps获取 export default function SomePage({ userData }) { return <div>Hello {userData.name}</div>; } - API路由做中转:将需要保密的操作放到
pages/api/下的路由中,客户端调用该API路由,由服务端使用环境变量处理请求后返回结果。
示例代码:// pages/api/get-user.js export default async function handler(req, res) { // 服务端访问保密变量 const secretKey = process.env.SECRET_API_KEY; const userData = await fetch(`https://api.example.com/user`, { headers: { Authorization: `Bearer ${secretKey}` } }).then(res => res.json()); res.status(200).json(userData); } // 客户端组件(包括_app)调用该API async function fetchUserData() { const res = await fetch('/api/get-user'); const data = await res.json(); return data; }
3. 在_app.js中使用服务端数据
_app.js的pageProps包含所有页面getServerSideProps返回的参数,也可通过useEffect调用API路由获取数据:
// pages/_app.js function MyApp({ Component, pageProps }) { // 直接使用pageProps中的服务端数据 // 或通过useEffect调用API获取数据 useEffect(() => { async function loadData() { const data = await fetch('/api/get-user').then(res => res.json()); // 处理数据逻辑 } loadData(); }, []); return <Component {...pageProps} />; } export default MyApp;
三、关键提醒
- 绝对不要将无
NEXT_PUBLIC_前缀的保密变量(如原始密钥)放到客户端代码中,哪怕通过props传递,也会被暴露。 - 不确定变量是否敏感时,默认只在服务端使用,通过API路由做中转处理。
内容的提问来源于stack exchange,提问作者Voley
相关产品推荐
相关产品推荐

