在React中使用秘密环境变量(Cloudflare Pages部署场景)
问题分析与解决方案
你当前的代码存在核心逻辑错误:Cloudflare Pages的中间件运行在Edge运行时环境中,不能直接在React前端组件里import并调用,前端代码无法直接访问Cloudflare的env对象,两者的运行环境完全隔离。以下是针对不同场景的正确解决方法:
场景1:授权密钥非敏感,可直接暴露给前端
如果你的authorization密钥不需要保密,可以通过Cloudflare Pages的构建时注入机制传递给前端,变量名必须以PUBLIC_为前缀:
- 在Cloudflare Pages项目的「设置-环境变量」中添加变量,命名为
PUBLIC_AUTHORIZATION,值填你的密钥。 - 前端组件直接使用该变量,无需中间件:
import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import ShareButtons from './ArticleShare'; import Navbar from './Navbar'; function Reader({activeCategory}) { const { id } = useParams(); const [article, setArticle] = useState(null); const [error, setError] = useState(null); const navigate = useNavigate(); useEffect(() => { const fetchArticle = async () => { try { const myHeaders = new Headers(); // 直接使用构建时注入的环境变量 myHeaders.append("authorization", process.env.PUBLIC_AUTHORIZATION); const requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; const response = await fetch(`https://myendpoint.dev/id/${id}`, requestOptions); const data = await response.json(); if (data.length > 0) { setArticle(data[0]); } } catch (err) { setError(err); } }; fetchArticle(); }, [id]); // 组件渲染逻辑... } export default Reader;
场景2:授权密钥敏感,需通过Edge函数中转
如果密钥不能暴露给前端,必须用Cloudflare Pages的Edge函数作为中间层,由函数在后端调用目标接口并返回结果:
- 在项目根目录创建
functions/api/article/[id].js文件(对应API路由/api/article/:id):
// Edge函数代码,运行在Cloudflare Edge环境 export async function onRequestGet(context) { const { id } = context.params; // 从Cloudflare env中获取敏感密钥 const { authorization } = context.env; try { // 由Edge函数调用目标接口,带上密钥 const response = await fetch(`https://myendpoint.dev/id/${id}`, { headers: { authorization } }); const data = await response.json(); return new Response(JSON.stringify(data), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ error: err.message }), { status: 500, headers: { "Content-Type": "application/json" } }); } }
- 前端组件调用自己的API路由,不再直接访问外部端点:
import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import ShareButtons from './ArticleShare'; import Navbar from './Navbar'; function Reader({activeCategory}) { const { id } = useParams(); const [article, setArticle] = useState(null); const [error, setError] = useState(null); const navigate = useNavigate(); useEffect(() => { const fetchArticle = async () => { try { // 调用Cloudflare Edge函数提供的API路由 const response = await fetch(`/api/article/${id}`); const data = await response.json(); if (data.length > 0) { setArticle(data[0]); } } catch (err) { setError(err); } }; fetchArticle(); }, [id]); // 组件渲染逻辑... } export default Reader;
内容的提问来源于stack exchange,提问作者Mrtsm
相关产品推荐
相关产品推荐

