passportjs + webpack 在生产中不起作用

passportjs + webpack doesn't work in production

我正在使用 passport 为我的应用程序的用户创建登录例程。我的应用程序是用 React 开发的,我使用 webpack 作为我的打包器。当我在开发环境中编译我的应用程序时一切正常,但是当我在生产环境中使用 webpack 编译它时,它会抛出以下错误:

/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/async.js:61
        fn = function () { throw arg; };
                           ^

TypeError: Cannot read property 'statusText' of undefined
    at /Users/macbook/Documents/lisapp/pos_lisa/built/server/index.js:15:194155
    at Strategy.strategy.error (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/passport/lib/middleware/authenticate.js:340:18)
    at verified (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/passport-local/lib/strategy.js:81:28)
    at /Users/macbook/Documents/lisapp/pos_lisa/built/server/index.js:15:228957
    at tryCatcher (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/util.js:16:23)
    at Promise.errorAdapter [as _rejectionHandler0] (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/nodeify.js:35:34)
    at Promise._settlePromise (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/promise.js:566:21)
    at Promise._settlePromise0 (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/promise.js:689:18)
    at Async._drainQueue (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (/Users/macbook/Documents/lisapp/pos_lisa/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)

我读了很多关于这个问题的资料,但 none 的解决方案对我有用。我缺少什么?我做错了什么?预先感谢对我有帮助的任何事情。这是我的 webpack 服务器配置

这是我的 webpack 服务器配置:

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const fs = require('fs');

var nodeModules = {
  "sendmail": "sendmail"
};

fs.readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1;
  })
  .forEach(function(mod) {
    nodeModules[mod] = 'commonjs ' + mod;
  });

const config = {
  entry: ['babel-polyfill', path.join(__dirname, '../source/server.jsx')],
  output: {
    filename: 'index.js',
    path: path.join(__dirname, '../built/server'),
    publicPath: process.env.NODE_ENV === 'production' ? 'https://pos.lisapp.co:3001/' : 'http://localhost:3001/'
  },
  module: {
    rules: [
      {
        test: /\.json$/,
        use: 'json-loader',
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['latest-minimal', 'react'],
          env: {
            production: {
              plugins: ['syntax-async-functions', 'bluebird-async-functions', 'transform-regenerator', 'transform-runtime'],
              presets: ['es2015']
            },
            development: {
              presets: ['latest-minimal']
            }
          }
        },
      },
      {
        test: /\.css$/,
        exclude: /(node_modules)/,
        loader: 'css-loader/locals?modules'
      },
      {
        test: /\.css$/,
        exclude: /(node_modules|source)\/(?!(react-table)\/).*/,
        loader: 'css-loader/locals?modules'
      },
      {
        test: /\.css$/,
        exclude: /(node_modules|source)\/(?!(react-touch-screen-keyboard)\/).*/,
        loader: 'css-loader/locals?modules'
      },
      {
        test: /\.inline.svg$/,
        loaders: [ 'babel-loader',
          {
            loader: 'react-svg-loader',
            query: {
              svgo: {
                plugins: [{removeTitle: false}],
                floatPrecision: 2
              }
            }
          }
        ]
      },
      {
        test: /\.jpe?g$|\.gif$|\.png$|^(?!.*\.inline\.svg$).*\.svg$/,
        loader: 'url-loader?limit=400000'
      },
    ],
  },
  externals: nodeModules,
  target: 'node',
  resolve: {
    extensions: ['.js', '.jsx', '.css', '.json'],
  },
  node: {
    fs: 'empty',
    dns: 'mock',
    net: 'mock',
    child_process: 'empty',
    tls: 'empty'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
      }
    }),
    new webpack.optimize.OccurrenceOrderPlugin(true),
    new ExtractTextPlugin({
      filename: '../statics/styles.css',
      ignoreOrder: true,
    })
  ]
  // watch: true,
};

if (process.env.NODE_ENV === 'production') {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
      mangle: {
        except: ['$super', '$', 'exports', 'require']
      }
    })
  );
}

module.exports = config;

这是我的 webpack 客户端配置:

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const webpack = require('webpack');

const config = {
  entry: ['babel-polyfill', path.join(__dirname, '../source/client.jsx')],
  output: {
    filename: 'app.js',
    path: path.join(__dirname, '../built/statics'),
    publicPath: process.env.NODE_ENV === 'production' ? 'https://pos.lisapp.co:3001/' : 'http://localhost:3001/'
  },
  module: {
    rules: [
      {
        test: /\.json$/,
        use: 'json-loader',
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['es2016', 'es2017', 'react'],
          plugins: ['transform-es2015-modules-commonjs'],
          env: {
            production: {
              plugins: ['syntax-async-functions', 'bluebird-async-functions', 'transform-regenerator', 'transform-runtime'],
              presets: ['es2015']
            },
            development: {
              plugins: ['transform-es2015-modules-commonjs']
            }
          }
        },
      },
      {
        test: /\.css$/,
        exclude: /(node_modules)/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader?modules',
        }),
      },
      {
        test: /\.css$/,
        exclude: /(node_modules|source)\/(?!(react-table)\/).*/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader',
        }),
      },
      {
        test: /\.css$/,
        exclude: /(node_modules|source)\/(?!(react-touch-screen-keyboard)\/).*/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader',
        }),
      },
      {
        test: /\.inline.svg$/,
        loader: 'babel-loader!react-svg-loader?' + JSON.stringify({
          svgo: {
            // svgo options
            plugins: [{removeTitle: false}],
            floatPrecision: 2
          }
        }),
      },
      {
        test: /\.jpe?g$|\.gif$|\.png$|^(?!.*\.inline\.svg$).*\.svg$/,
        loader: 'url-loader?limit=400000'
      },
    ],
  },
  target: 'web',
  resolve: {
    extensions: ['.js', '.jsx', '.css', '.json'],
  },
  node: {
    fs: 'empty',
    dns: 'mock',
    net: 'mock',
    child_process: 'empty',
    tls: 'empty'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
      }
    }),
    new webpack.optimize.OccurrenceOrderPlugin(true),
    new ExtractTextPlugin({
      filename: '../statics/styles.css',
      ignoreOrder: true,
    })
  ]
  // watch: true,
};

if (process.env.NODE_ENV === 'production') {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
      mangle: {
        except: ['$super', '$', 'exports', 'require']
      }
    })
  );
}

module.exports = config;

这是我调用护照策略进行身份验证的节点函数:

lisaApp.post('/login', function(req, res, next) {
  const validationResult = validateLoginForm(req.body);
  if (!validationResult.success) {
    return res.status(400).json({
      success: false,
      message: validationResult.message,
      errors: validationResult.errors
    });
  }

  passport.authenticate('local', function(err, user, token) {
    if (err) {
      if (err.response.statusText === 'Unauthorized') {
        return res.status(400).json({
          success: false,
          message: 'fail'
        });
      }

      return res.status(500).json({
        success: false,
        message: 'fail'
      });
    }

    req.logIn(user, function(err) {
      if (err) { console.log(err); }

      return res.json({
        success: true,
        redirectUrl: '/dashboard',
        message: 'success',
        token,
        client: user
      });
    });
  })(req, res, next);
});

好吧,经过 1 天的证明所有事情后,考虑到问题来自使用 'bluebird' 解决 Promise 的异步函数,我决定加入一些逻辑。这里的问题是,在开发中,webpack 插件接受 PassportJS 连接作为 Promises,但是当我将我的应用程序编译到生产环境时,必须使用 async/await 来解析 Promises,而 PassportJS 本身不能很好地与异步函数一起工作.所以我们必须手动完成。您必须使用 async/await 手动管理策略,如下所示:

exports.localStrategy = new LocalStrategy({
  usernameField: 'userclient',
  passwordField: 'password',
  session: false,
  passReqToCallback: true
}, async (req, userclient, password, done) => {
  var authData = {
    userclient,
    password
  }

  var authToken = await ClientApi.authenticate(authData);

  if(authToken) {
    var token = authToken.data
    var user = await ClientApi.getClient(userclient);

    if (user) {
      user.token = token
      const userData = {
        id: (user.data.client_id) ? user.data.client_id : user.data.clientId,
        userclient: (user.data.userclient) ? user.data.userclient : ((user.data.sellerUserName) ? user.data.sellerUserName : user.data.kitchenUserName),
        codeOfSeller: (user.data.client_id) ? false : ((user.data.codeOfSeller) ? user.data.codeOfSeller : 'kitchenSeller'),
        token: user.token
      };

      done(null, userData, token);
    } else {
      done(err);
    }

  } else {
    done(err);
  }
})

希望对某人有所帮助,我真的浪费了很多时间,但我学到了。