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);
}
})
希望对某人有所帮助,我真的浪费了很多时间,但我学到了。
我正在使用 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);
}
})
希望对某人有所帮助,我真的浪费了很多时间,但我学到了。