我正在尝试使用Express服务器学习React和Webpack。 我想让Webpack HMR与React Hot Loader一起工作。当我启动服务器时,它也应该启动webpack进程,但是我收到以下错误:
throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
错误,我想,它告诉我我的配置不正确。
在我遇到此错误之前(当我将Webpack从1.14.0更新到2.2.0时发生),它确实达到了入口点(app / main.jsx),但它没有得到我想要的用React渲染,我不知道为什么。它导致了Unexpected Token错误,建议找一个加载器来处理该文件类型。
这是我的 webpack.config.js :
var path = require('path');
var webpack = require('webpack');
var config = {
devtool: 'cheap-module-eval-source-map',
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'webpack-dev-middleware/client',
'./app/main'
],
output: {
path: path.join(__dirname, 'public', 'js'),
filename: 'bundle.js',
publicPath: './public/'
},
resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}),
],
module: {
loaders: [
{
test: /\.css$/,
loader: 'style!css'
},
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
},
{
test: /\.jsx$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel-loader'],
include: path.join(__dirname, 'app'),
query: {
presets: ['es2015', 'react']
}
}
]
}
};
if (process.env.NODE_ENV === 'production') {
config.plugins.push(
new webpack.optimize.UglifyJsPlugin({
compressor: {
screw_ie8: true,
warnings: false
}
})
);
}
module.exports = config;
我不是很确定这一切,我从之前正在使用的起动器中挑选了线,而另一个来自发电机。
此配置用于我的 server.js 文件:
var express = require('express');
var path = require('path');
var dotenv = require('dotenv');
var React = require('react');
var ReactDOM = require('react-dom/server');
var Router = require('react-router');
var Provider = require('react-redux').Provider;
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
// Load environment variables from .env file
dotenv.load();
// ES6 Transpiler
require('babel-core/register');
require('babel-polyfill');
// React and Server-Side Rendering
var routes = require('./app/routes');
var configureStore = require('./app/store/configureStore').default;
var app = express();
var compiler = webpack(config);
var hbs = exphbs.create({
defaultLayout: 'main',
helpers: {
ifeq: function(a, b, options) {
if (a === b) {
return options.fn(this);
}
return options.inverse(this);
},
toJSON : function(object) {
return JSON.stringify(object);
}
}
});
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
app.set('port', process.env.PORT || 3000);
app.use(compression());
app.use(sass({ src: path.join(__dirname, 'public'), dest: path.join(__dirname, 'public') }));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressValidator());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
if (app.get('env') === 'development') {
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
}
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
}).listen(8080, 'localhost', function ( err, result ) {
if (err) {
return console.log(err);
}
console.log('listening at http://localhost:8080');
})
// React server rendering
app.use(function(req, res) {
var initialState = {
messages: {}
};
var store = configureStore(initialState);
Router.match({ routes: routes.default(store), location: req.url }, function(err, redirectLocation, renderProps) {
if (err) {
res.status(500).send(err.message);
} else if (redirectLocation) {
res.status(302).redirect(redirectLocation.pathname + redirectLocation.search);
} else if (renderProps) {
var html = ReactDOM.renderToString(React.createElement(Provider, { store: store },
React.createElement(Router.RouterContext, renderProps)
));
res.render('layouts/main', {
html: html,
initialState: store.getState()
});
} else {
res.sendStatus(404);
}
});
});
// Production error handler
if (app.get('env') === 'production') {
app.use(function(err, req, res, next) {
console.error(err.stack);
res.sendStatus(err.status || 500);
});
}
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
module.exports = app;
我使用npm start
命令启动项目,这是我的 package.json :
{
"name": "noisy-violet",
"version": "1.0.0",
"description": "My app description",
"scripts": {
"build": "webpack --display-error-details",
"deploy": "npm test && git push heroku master",
"postinstall": "npm run build",
"start": "node server.js",
"test": "npm run test:client && npm run test:server",
"test:client": "mocha test/client --recursive --compilers js:babel-register",
"test:server": "mocha test/server --recursive --compilers js:babel-register"
},
"dependencies": {
"babel": "^6.5.2",
"babel-core": "^6.7.2",
"babel-loader": "^6.2.4",
"babel-plugin-react-transform": "^2.0.2",
"babel-polyfill": "^6.7.2",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"body-parser": "^1.15.1",
"compression": "^1.6.2",
"cookie-parser": "^1.4.1",
"dotenv": "^2.0.0",
"es5-shim": "^4.5.9",
"express": "^4.13.4",
"express-handlebars": "^3.0.0",
"express-validator": "^2.20.4",
"imports-loader": "^0.7.0",
"jquery": "^3.1.1",
"morgan": "^1.7.0",
"node-sass-middleware": "^0.9.7",
"nodemailer": "^2.3.0",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-redux": "4.4.1",
"react-router": "^2.4.0",
"react-sizeme": "^2.2.0",
"react-three-renderer": "^3.0.2",
"react-transform-catch-errors": "^1.0.2",
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.2.4",
"redux": "^3.3.1",
"redux-logger": "^2.6.1",
"redux-promise": "^0.5.3",
"redux-thunk": "^2.0.1",
"three": "^0.82.1",
"webpack": "^2.2.0",
"webpack-dev-middleware": "^1.6.1",
"webpack-hot-middleware": "^2.10.0",
"whatwg-fetch": "^0.11.0"
},
"devDependencies": {
"babel-plugin-rewire": "1.0.0-rc-3",
"babel-register": "^6.8.0",
"chai": "^3.5.0",
"enzyme": "^2.3.0",
"fetch-mock": "3.0.2",
"mocha": "^2.4.5",
"react-addons-perf": "^15.4.2",
"react-addons-test-utils": "^15.0.2",
"react-hot-loader": "^1.3.1",
"redux-mock-store": "^1.0.2",
"sinon": "^1.17.3",
"sinon-chai": "^2.8.0",
"supertest": "^1.2.0",
"webpack-dev-server": "^1.16.2"
},
"engines": {
"node": "6.1.0"
}
}
截至目前,我不知道该怎么做。
答案 0 :(得分:0)
resolve.extensions
不再需要空字符串,因此您可以从那里删除数组中的''
。
module.loaders
现在是module.rules
。子loader
现在是use
,看起来像一个数组优先于字符串。然后在那里,query
现在是options
在现在“使用”的“加载器”中,您需要在名称的末尾加上-loader
。因此,您react-hot
的位置现在需要react-hot-loader
插件和其他东西还有很多,但希望这会让你有个好的开始。查看"Migrating from v1 to v2"页面上的所有差异。