Node.js Express如何将process.env.API_KEY传递给公共app.js
解决方案
首先明确:public目录下的app.js运行在用户浏览器环境,不存在Node.js的process对象,无法直接读取后端的process.env变量,必须由后端主动把值传递给前端。
重要提醒:如果你的API_KEY是付费、带调用权限的私密服务端密钥,绝对不要直接传到前端——所有访问站点的用户都能通过浏览器开发者工具拿到这个密钥,很容易被盗用刷取接口额度。这种场景请把需要用到密钥的第三方API调用逻辑放到后端,前端仅请求你自己的服务端接口即可。如果该密钥本身就是设计给前端使用的可公开公钥,可使用下面两种方案传递。
方案1:HTML注入全局变量(适合公钥场景)
在返回首页HTML时把密钥注入到页面全局变量,前端JS直接读取即可。
- 修改后端
index.js代码,调整中间件顺序(符合Express最佳实践),增加首页注入逻辑:
const express = require('express'); const fs = require('fs'); const app = express(); require('dotenv').config(); const PORT = 3000; // 先注册静态资源托管 app.use(express.static('public')); // 单独处理首页路由,替换占位符注入密钥 app.get('/', (req, res) => { let html = fs.readFileSync('./public/index.html', 'utf-8'); html = html.replace( '<!--API_KEY_INJECT-->', `<script>window.API_KEY = "${process.env.API_KEY}"</script>` ); res.send(html); }) app.listen(PORT, () => console.log(`Starting server: http://localhost:${PORT}`));
- 打开
public/index.html,在引入app.js的标签前加上占位符:
<!-- 其他页面内容 --> <!--API_KEY_INJECT--> <script src="/app.js"></script>
- 前端
app.js直接读取全局变量即可使用:
document.addEventListener('readystatechange', (event) => { if (event.target.readyState === 'complete') { initApp(); } }); const initApp = () => { // 直接读取window.API_KEY使用 console.log('获取到的API_KEY:', window.API_KEY); }
方案2:后端提供配置接口(适合公钥场景)
单独写一个返回公开配置的接口,前端初始化时先请求配置再启动逻辑。
- 后端增加配置接口:
const express = require('express'); const app = express(); require('dotenv').config(); const PORT = 3000; app.use(express.static('public')); // 仅返回可公开的配置项 app.get('/api/get-config', (req, res) => { res.json({ apiKey: process.env.API_KEY }) }) app.listen(PORT, () => console.log(`Starting server: http://localhost:${PORT}`));
- 前端
app.js启动前先拉取配置:
document.addEventListener('readystatechange', async (event) => { if (event.target.readyState === 'complete') { // 先拉取公钥配置 const configRes = await fetch('/api/get-config'); const config = await configRes.json(); window.API_KEY = config.apiKey; initApp(); } }); const initApp = () => { console.log('获取到的API_KEY:', window.API_KEY); }
方案3:私密密钥的标准处理方式(推荐)
如果密钥不能公开,全程不要把密钥传到前端,所有需要用到密钥的请求都由后端代理转发:
- 后端封装代理接口,请求第三方服务时在服务端带上密钥:
const express = require('express'); const app = express(); const axios = require('axios'); // 需提前安装axios依赖 require('dotenv').config(); const PORT = 3000; app.use(express.static('public')); // 代理第三方API请求 app.get('/api/xxx-service', async (req, res) => { try { // 从query里拿前端传的业务参数 const { param1 } = req.query; // 服务端请求第三方接口时带密钥,不会暴露给前端 const thirdRes = await axios.get(`https://third-party-service.com/api`, { params: { param1, key: process.env.API_KEY } }); res.json(thirdRes.data); } catch (err) { res.status(500).json({ msg: '请求失败' }); } }) app.listen(PORT, () => console.log(`Starting server: http://localhost:${PORT}`));
- 前端
app.js直接请求自己的后端接口即可,全程不需要接触密钥:
document.addEventListener('readystatechange', (event) => { if (event.target.readyState === 'complete') { initApp(); } }); const initApp = async () => { // 请求自己的后端接口,不需要传密钥 const res = await fetch('/api/xxx-service?param1=test'); const data = await res.json(); console.log(data); }
内容的提问来源于stack exchange,提问作者200gSoft
相关产品推荐
相关产品推荐

