简体   繁体   中英

Error handler ignored when NODE_ENV=production

I am building a simple REST API with Node/Express, and I'm having a hard time when I deploy it to production. When NODE_ENV=development , everything works as expected. I get back the JSON error and the correct status code. When NODE_ENV=production , I only get back an HTML page with the default error message and nothing else. I can read the status code, but I need to have access to the full JSON payload to identify the errors better. This is my code:

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;

This is the notFoundMiddleware :

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

This is the 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 });
};

If you are runing on production server, try to use some logging provider like "papertrailapp" to see the error occurs in your app.

在此处输入图片说明

I've just stumbled upon the same problem. It turned out it's caused by a transpiler optimization applied when building production bundle - this one: https://babeljs.io/docs/en/babel-plugin-minify-dead-code-elimination

Express' error handlers should have the signature (err, req, res, next) => { ... } (be of arity 4). In your example next is not used anywhere in errorMiddleware function body and thus it gets eliminated (optimized-out) from function signature in production code.

Solution :

  • use keepFnArgs: true plugin option - possibly through https://webpack.js.org/plugins/babel-minify-webpack-plugin/ webpack configuration:

     var MinifyPlugin = require("babel-minify-webpack-plugin") module.exports = { // ... optimization: { minimizer: [ new MinifyPlugin({ deadcode: { keepFnArgs: true, }, }, {}), ], } // ... }
  • or alternatively pretend in your code that this argument is used:
     const errMiddleware = (err, req, res, _next) => { // ... your code ... // ... // cheat here: _next }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM