Nuxt.js服务端获取存储Bearer Token遇FS模块引入问题求助
解决Nuxt ServerMiddleware中无法引入fs模块的问题及Bearer Token存储最佳实践
首先,咱们来拆解你遇到的核心问题:你明明把代码放在serverMiddleware里,却还是碰到了fs模块找不到的报错,这是因为文件位置和Nuxt的默认处理逻辑不匹配。根目录下的middleware文件夹是页面级中间件的默认位置,Nuxt会默认把这里的代码同时打包给客户端和服务端——而客户端浏览器根本没有fs模块,自然就报错了。
第一步:修正ServerMiddleware的文件位置与配置
Nuxt专门为服务端中间件提供了server/middleware目录(如果没有就手动创建),把你的bearerToken.ts移到这个目录下,Nuxt会明确将其标记为仅服务端运行的代码,不会打包到客户端。
修改后的nuxt.config.ts配置可以简化成这样:
export default defineNuxtConfig({ serverMiddleware: [ // 直接指定路径,Nuxt会自动识别为服务端中间件 '~/server/middleware/bearerToken.ts' // 或者更明确的对象配置(可选) // { path: '/', handler: '~/server/middleware/bearerToken.ts', mode: 'server' } ] })
第二步:修正中间件代码中的fs引入逻辑
在TypeScript里建议用ES模块的import方式引入fs,同时加上process.server的判断(虽然放在server/middleware里已经是服务端专属,但加一层判断更稳妥):
import type { IncomingMessage, ServerResponse } from 'http' import fs from 'fs' import path from 'path' export default function bearerTokenMiddleware(req: IncomingMessage, res: ServerResponse, next: () => void) { try { // 确保只在服务端执行文件操作 if (process.server) { // 建议把Token文件放在项目根目录的专属文件夹里,避免和源码混在一起 const tokenDir = path.resolve(process.cwd(), '.nuxt', 'tokens') const tokenPath = path.join(tokenDir, 'bearer.token') // 先创建目录(避免文件写入时目录不存在报错) if (!fs.existsSync(tokenDir)) { fs.mkdirSync(tokenDir, { recursive: true }) } // 这里写你的Token读取/生成逻辑 if (fs.existsSync(tokenPath)) { const existingToken = fs.readFileSync(tokenPath, 'utf-8') // 可以把Token挂载到req对象上,方便后续API请求使用 (req as any).bearerToken = existingToken } else { // 调用OAuth令牌端点获取新Token的逻辑 // 比如用axios请求: // const tokenResponse = await axios.post('https://your-oauth-endpoint/token', { // client_id: 'YOUR_CLIENT_ID', // client_secret: 'YOUR_CLIENT_SECRET', // grant_type: 'client_credentials' // }) // const newToken = tokenResponse.data.access_token // fs.writeFileSync(tokenPath, newToken, 'utf-8') // (req as any).bearerToken = newToken } } } catch (e) { console.error('处理Bearer Token时发生错误:', e) } next() }
第三步:关于Bearer Token存储的最佳实践
你当前用本地文件存储Token的方案,在单实例开发环境下可以用,但生产环境有明显缺陷:
- 如果是多实例部署(比如Docker集群、云服务器多节点),每个实例的文件系统独立,Token无法共享,会导致重复请求OAuth端点,容易触发限流。
- 文件存储没有自动过期机制,需要手动处理Token的刷新逻辑。
更推荐的生产级方案:
- 分布式缓存(如Redis):所有服务实例共享Token,配合过期时间自动刷新,是最稳妥的方案。Nuxt 3可以通过
useStorage配置Redis驱动,直接调用缓存API。 - 服务端内存缓存:适合单实例部署,用Node.js的
Map或第三方缓存库(如lru-cache)存储Token,加上过期时间,每次请求前检查是否过期,过期则重新获取。 - Nuxt内置存储:Nuxt 3的
useStorage默认支持内存存储,开发时可以快速上手,生产环境再切换到Redis。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

