当 NODE_ENV=production 时忽略错误处理程序

Posted

技术标签:

【中文标题】当 NODE_ENV=production 时忽略错误处理程序【英文标题】:Error handler ignored when NODE_ENV=production 【发布时间】:2019-01-18 19:17:07 【问题描述】:

我正在使用 Node/Express 构建一个简单的 REST API,但在将其部署到生产环境时遇到了困难。当NODE_ENV=development 时,一切都按预期工作。我得到了 JSON 错误和正确的状态码。当NODE_ENV=production 时,我只返回一个带有默认错误消息的 html 页面,没有别的。我可以读取状态代码,但我需要访问完整的 JSON 有效负载以更好地识别错误。这是我的代码:

import Promise from 'bluebird'; // eslint-disable-line no-unused-vars
import express from 'express';
import config from './config';
import routes from './routes';
import  errorMiddleware, notFoundMiddleware  from './middlewares/error.middleware';
import mongoose from './config/mongoose.config';

// create app
const app = express();

(async () => 
  // connect to mongoose
  await mongoose.connect();

  // pretty print on dev
  if (process.env.NODE_ENV !== 'production') 
    app.set('json spaces', 2);
  

  // apply express middlewares
  app.use(express.json());

  // register v1 routes
  app.use('/v1', routes);

  // catch errors
  app.use(notFoundMiddleware);
  app.use(errorMiddleware);

  // start server
  app.listen(config.port, () => console.info(`server started on port $config.port`));
)();

export default app;

这是notFoundMiddleware

export default (req, res, next) => next(new Error('Not Found'));

这是errorMiddleware

const errorMiddleware = (err, req, res, next) => 
  console.log('test'); // this works in development, but not in production
  const error = 
    status: err.status,
    message: err.message
  ;

  if (err.errors) 
    error.errors = err.errors;
  

  if (process.env.NODE_ENV !== 'production' && err.stack) 
    error.stack = err.stack;
  

  return res.status(error.status || 500).send( error );
;

【问题讨论】:

em...当你有生产模式时你有if,那么你不会只发送堆栈跟踪消息和状态。if (process.env.NODE_ENV !== 'production' && err.stack) error.stack = err.stack; @DmytroMysak 是的,那是因为我不想在生产中使用堆栈。问题是我也没有收到状态或消息。 从 npm 模块文档看来,您必须使用 ApiErrorsMiddleware 才能获得 JSON 响应。 我无法重现您的问题,您能否向我们展示一个示例,说明您返回调用错误处理程序的错误的位置? (例如next(new Error.. 您是否在 nginx 或类似的平台下提供 API? 【参考方案1】:

如果您在生产服务器上运行,请尝试使用诸如“papertrailapp”之类的日志记录提供程序来查看您的应用中发生的错误。

【讨论】:

【参考方案2】:

我刚刚偶然发现了同样的问题。原来这是由构建生产包时应用的转译器优化引起的 - 这个:https://babeljs.io/docs/en/babel-plugin-minify-dead-code-elimination

Express 的错误处理程序应具有签名 (err, req, res, next) => ... (为 4 位元数)。在您的示例中,next 未在 errorMiddleware 函数体中的任何位置使用,因此它会从生产代码中的函数签名中消除(优化)。

解决方案

使用keepFnArgs: true 插件选项 - 可能通过https://webpack.js.org/plugins/babel-minify-webpack-plugin/ webpack 配置:

var MinifyPlugin = require("babel-minify-webpack-plugin")
module.exports = 
    // ...

    optimization: 
        minimizer: [
            new MinifyPlugin(
                deadcode: 
                    keepFnArgs: true,
                ,
            , ),
        ],
    

    // ...

或者在您的代码中假装使用了此参数:
const errMiddleware = (err, req, res, _next) => 
    // ... your code ...
    // ...
    // cheat here:
    _next

【讨论】:

以上是关于当 NODE_ENV=production 时忽略错误处理程序的主要内容,如果未能解决你的问题,请参考以下文章

if(process.env.NODE_ENV === 'production') 总是假的

if(process.env.NODE_ENV ==='production')总是假的

使用带有 NODE_ENV=production 的 spawn 函数

vue 构建而不覆盖 NODE_ENV

无法让 NODE_ENV 在开班时粘在我的 MEAN 堆栈上

如何在 Windows 上设置 NODE_ENV=production?