如何为NextJS API配置全局错误处理以实现外部系统错误上报?
在Next.js中实现全局API错误处理(支持NewRelic等外部系统)
完全可以配置全局错误处理程序包裹所有Next.js API路由,无需逐个修改文件,完美遵循DRY原则。以下分两种路由方案给出具体实现方式:
Pages Router(Next.js 12及更早版本)
1. 编写全局错误处理包装器
创建通用的错误处理高阶函数,负责捕获错误、收集堆栈信息并推送到NewRelic:
// utils/apiErrorHandler.js import newrelic from 'newrelic'; export const withErrorHandling = (handler) => async (req, res) => { try { await handler(req, res); } catch (error) { // 提取堆栈跟踪信息 const stackTrace = error.stack || '无可用堆栈信息'; console.error('API 错误:', error.message, stackTrace); // 推送错误到NewRelic newrelic.noticeError(error, { stackTrace, requestPath: req.path, requestMethod: req.method }); // 返回标准化错误响应 res.status(500).json({ success: false, message: '服务器内部错误', stack: process.env.NODE_ENV === 'development' ? stackTrace : undefined }); } };
2. 自定义服务器自动包装所有API路由
通过自定义服务器劫持require方法,自动为pages/api下的所有路由应用错误处理包装器,无需逐个修改API文件:
// server.js const next = require('next'); const http = require('http'); const { withErrorHandling } = require('./utils/apiErrorHandler'); const path = require('path'); const isDev = process.env.NODE_ENV !== 'production'; const app = next({ dev: isDev }); const requestHandler = app.getRequestHandler(); // 劫持模块加载逻辑,自动包装API路由 const originalRequire = require; require = function (modulePath) { const module = originalRequire(modulePath); // 判断是否为pages/api目录下的路由文件 if (modulePath.includes(path.join('pages', 'api')) && typeof module.default === 'function') { module.default = withErrorHandling(module.default); } return module; }; app.prepare().then(() => { http.createServer((req, res) => { requestHandler(req, res); }).listen(3000, (err) => { if (err) throw err; console.log('> 服务已启动:http://localhost:3000'); }); });
3. 修改启动脚本
在package.json中替换默认启动命令,使用自定义服务器:
"scripts": { "dev": "node server.js", "build": "next build", "start": "NODE_ENV=production node server.js" }
App Router(Next.js 13+)
对于App Router,推荐使用Babel插件自动注入错误处理逻辑,避免逐个修改app/api下的路由文件:
1. 创建Babel插件
// babel-plugin-wrap-api-handlers.js module.exports = function () { return { visitor: { ExportDefaultDeclaration(path) { // 仅处理app/api目录下的文件 if (this.file.opts.filename.includes('/app/api/')) { const wrapper = this.file.addImport('utils/apiErrorHandler', 'withErrorHandling'); path.node.declaration = this.types.callExpression(wrapper, [path.node.declaration]); } } } }; };
2. 配置Babel
在项目根目录创建.babelrc或修改next.config.js中的Babel配置:
{ "plugins": ["./babel-plugin-wrap-api-handlers.js"] }
3. 复用错误处理包装器
直接使用Pages Router中编写的withErrorHandling函数即可,逻辑完全通用。
关键说明
- 两种方案均无需手动修改每个API路由文件,完全遵循DRY原则。
- 错误处理逻辑可统一维护,如需调整推送目标(如切换到其他监控系统),仅需修改
withErrorHandling函数。 - 生产环境建议隐藏堆栈信息,避免泄露敏感代码细节。
内容的提问来源于stack exchange,提问作者Swanand Keskar
相关产品推荐
相关产品推荐

