1

我正在尝试使用 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"
  }
}

到目前为止,我不知道该怎么做。

4

1 回答 1

0

resolve.extensions不再需要空字符串,因此您可以''从那里的数组中删除。

module.loaders现在是module.rules。subloader现在use看起来像一个数组而不是字符串。然后在里面,query就是现在options

在您现在“使用”的“加载程序”中,您需要-loader在名称末尾包含 。所以你react-hot现在需要在哪里react-hot-loader

插件和其他东西还有更多,但希望这能让你有一个好的开始。查看他们的“从 v1 迁移到 v2”页面上的所有差异。

于 2017-01-23T00:31:29.017 回答