在gatsby-source-graphql的headers配置中异步生成并存储Bearer token
解决方案
方案1:内存缓存(推荐,适配绝大多数场景)
Gatsby 配置运行在 Node.js 进程中,你可以直接在模块作用域声明变量存储 token 和过期时间,单次构建/开发过程中所有请求都会复用同一份缓存,不需要重复调用鉴权接口,适配90%以上的使用场景。
修改后的getAuthToken代码如下:
require("dotenv").config({ path: `.env.${process.env.NODE_ENV}`, }); const axios = require("axios"); // 内存缓存变量 let cachedToken = null; let tokenExpiryTime = 0; const getAuthToken = async () => { const now = Date.now(); // 缓存未过期直接返回 if (cachedToken && now < tokenExpiryTime) { return cachedToken; } // Node.js 低版本兼容替换btoa为Buffer写法,兼容性更强 const basicToken = Buffer.from( `${process.env.CTP_CLIENT_ID}:${process.env.CTP_CLIENT_SECRET}` ).toString('base64'); try { const { data } = await axios.post( `${process.env.CTP_AUTH_URL}/oauth/token?grant_type=client_credentials`, null, { headers: { Authorization: `Basic ${basicToken}`, }, } ); cachedToken = `Bearer ${data.access_token}`; // 提前10分钟过期,避免临界时间使用失效token tokenExpiryTime = now + (data.expires_in - 600) * 1000; return cachedToken; } catch (err) { console.warn('获取鉴权token失败:', err); // 兜底逻辑:如果还有即将过期的旧token可以临时使用,也可以直接抛出错误终止构建 if (cachedToken && now < tokenExpiryTime + 600 * 1000) { return cachedToken; } throw err; } }; // 下方的module.exports配置保持原有逻辑即可,无需修改
方案2:本地文件缓存(支持多次构建复用)
如果需要重启 Gatsby 开发服务、多次执行构建命令时也不需要重新请求token,可以将token和过期时间写入本地临时文件缓存。
- 先在项目根目录
.gitignore中添加一行.token.cache,避免缓存文件被提交到代码仓库泄露凭证 - 修改
getAuthToken代码如下:
const fs = require('fs/promises'); const path = require('path'); const CACHE_FILE_PATH = path.resolve(__dirname, '.token.cache'); const getAuthToken = async () => { const now = Date.now(); // 先读取本地缓存 try { const cacheContent = await fs.readFile(CACHE_FILE_PATH, 'utf8'); const { token, expiry } = JSON.parse(cacheContent); if (token && now < expiry) { return token; } } catch (e) { // 缓存不存在/解析失败直接忽略,重新请求即可 } // 此处请求token的逻辑和方案1完全一致,请求成功后写入本地缓存 // ... 请求逻辑省略 const newToken = `Bearer ${data.access_token}`; const newExpiry = now + (data.expires_in - 600) * 1000; await fs.writeFile(CACHE_FILE_PATH, JSON.stringify({ token: newToken, expiry: newExpiry }), 'utf8'); return newToken; };
内容的提问来源于stack exchange,提问作者Wojciech Jeleń
相关产品推荐
相关产品推荐

