Next.js启动服务前需访问环境变量,如何在next命令前执行vault脚本?
解决方案
方案1:修改package.json脚本串行执行
npm/yarn/pnpm默认会按&&连接的命令串行执行,前一个命令退出码为0才会执行后续命令,直接修改scripts配置即可:
{ "scripts": { "fetch:secrets": "node fetch-vault-secrets.js", "dev": "npm run fetch:secrets && next dev", "build": "npm run fetch:secrets && next build", "start": "next start" } }
注意:要确保
fetch-vault-secrets.js拉取完密钥、写入.env文件后才主动退出,不要留未处理的异步逻辑就提前退出,否则会出现密钥还没写完就启动Next.js的问题。如果脚本内是异步请求Vault,要把逻辑包在async函数里,执行成功调用process.exit(0),出错就调用process.exit(1)终止后续流程。
fetch-vault-secrets.js 参考实现
const fs = require('fs/promises') const axios = require('axios') async function main() { // 从环境变量读取Vault认证信息 const { VAULT_ADDR, ROLE_ID, VAULT_SECRET_ID } = process.env if (!VAULT_ADDR || !ROLE_ID || !VAULT_SECRET_ID) { console.error('缺少Vault认证必要环境变量') process.exit(1) } try { // 登录Vault获取token const loginRes = await axios.post(`${VAULT_ADDR}/v1/auth/approle/login`, { role_id: ROLE_ID, secret_id: VAULT_SECRET_ID }) const vaultToken = loginRes.data.auth.client_token // 拉取对应路径的密钥 const secretRes = await axios.get(`${VAULT_ADDR}/v1/你的密钥存储路径`, { headers: { 'X-Vault-Token': vaultToken } }) const secrets = secretRes.data.data // 写入.env文件 const envContent = Object.entries(secrets).map(([k, v]) => `${k}=${v}`).join('\n') await fs.writeFile('.env', envContent, 'utf8') process.exit(0) } catch (err) { console.error('拉取Vault密钥失败', err.message) process.exit(1) } } main()
方案2:使用pre钩子自动执行前置脚本
npm/yarn/pnpm都支持pre脚本钩子,命名为pre[脚本名]的脚本会自动在对应脚本执行前运行,不需要手动加&&:
{ "scripts": { "fetch:secrets": "node fetch-vault-secrets.js", "predev": "npm run fetch:secrets", "prebuild": "npm run fetch:secrets", "dev": "next dev", "build": "next build" } }
这种方式的好处是不管你怎么启动dev和build命令,都会自动先跑密钥拉取逻辑,不会出现漏执行的情况。
方案3:Next.js配置层注入(适合密钥不落地场景)
如果你不想把密钥落地到本地.env文件,可以直接在next.config.js里引入密钥拉取逻辑,Next.js启动时会优先加载这个配置文件:
// next.config.js const fetchVaultSecrets = require('./fetch-vault-secrets') module.exports = async () => { // 先拉取Vault密钥,直接注入到process.env const secrets = await fetchVaultSecrets() Object.assign(process.env, secrets) return { // 你的其他Next.js配置 reactStrictMode: true, } }
注意:这种方式仅在Next.js的Node.js运行时生效,浏览器端的环境变量还是需要按照Next.js规则,以
NEXT_PUBLIC_开头才会被注入到客户端。
额外注意事项
- 存放VAULT_SECRET_ID和ROLE_ID的文件不要提交到Git仓库,要加入
.gitignore - 本地开发时这两个ID可以存放到本地的
.env.local文件中,Next.js会自动加载这个文件的变量给fetch-vault-secrets.js使用 - 生产环境的ROLE_ID和SECRET_ID建议通过部署平台的环境变量能力注入,不要落地到磁盘
内容的提问来源于stack exchange,提问作者Usama Tahir
相关产品推荐
相关产品推荐

