如何允许webpack-dev-server允许来自react-router的入口点

我正在创build一个应用程序,在开发中使用webpack-dev-server和react-router。

webpack-dev-server似乎是build立在假设你将在一个地方(即“/”)拥有一个公共入口点,而react-router允许无限量的入口点的。

我想要webpack-dev-server的好处,特别是热重载function,这对于提高生产效率非常有用,但我仍然希望能够加载在react-router中设置的路由。

一个人怎么能够一起工作呢? 你可以在webpack-dev-server的前面运行一个express服务器吗?

我build立了一个代理来实现这一点:

你有一个普通的快递networking服务器,可以在任何路线上为index.html服务,除非它是一个资产路线。 如果它是一个资产,请求被代理到web-dev-server

您的反应热入口点仍将直接指向webpack dev服务器,所以热重新加载仍然有效。

我们假设你在8081上运行webpack-dev-server,在8080上运行你的代理。你的server.js文件如下所示:

"use strict"; var webpack = require('webpack'); var WebpackDevServer = require('webpack-dev-server'); var config = require('./make-webpack-config')('dev'); var express = require('express'); var proxy = require('proxy-middleware'); var url = require('url'); ## --------your proxy---------------------- var app = express(); ## proxy the request for static assets app.use('/assets', proxy(url.parse('http://localhost:8081/assets'))); app.get('/*', function(req, res) { res.sendFile(__dirname + '/index.html'); }); # -----your-webpack-dev-server------------------ var server = new WebpackDevServer(webpack(config), { contentBase: __dirname, hot: true, quiet: false, noInfo: false, publicPath: "/assets/", stats: { colors: true } }); ## run the two servers server.listen(8081, "localhost", function() {}); app.listen(8080); 

现在在webpackconfiguration中使你的入口点如下所示:

  entry: [ './src/main.js', 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:8081' ] 

注意直接调用8081进行热备份

还要确保你传递一个绝对的url到output.publicPath选项:

  output: { publicPath: "http://localhost:8081/assets/", // ... } 

您应该将WebpackDevServer设置为true才能正常工作。 这里有一个小例子(适合你的目的):

 var webpack = require('webpack'); var WebpackDevServer = require('webpack-dev-server'); var config = require('./webpack.config'); var port = 4000; var ip = '0.0.0.0'; new WebpackDevServer(webpack(config), { publicPath: config.output.publicPath, historyApiFallback: true, }).listen(port, ip, function (err) { if(err) { return console.log(err); } console.log('Listening at ' + ip + ':' + port); }); 

对于任何其他人可能仍然在寻找这个答案。 我放了一个简单的代理旁路,实现这一点,没有太多的麻烦,configuration进入webpack.config.js

我相信有更多的优雅的方式来testing本地内容使用正则expression式,但这符合我的需求。

 devServer: { proxy: { '/**': { //catch all requests target: '/index.html', //default target secure: false, bypass: function(req, res, opt){ //your custom code to check for any exceptions //console.log('bypass check', {req: req, res:res, opt: opt}); if(req.path.indexOf('/img/') !== -1 || req.path.indexOf('/public/') !== -1){ return '/' } if (req.headers.accept.indexOf('html') !== -1) { return '/index.html'; } } } } } 

我想添加到案例的答案,当你运行一个同构的应用程序(即渲染React组件服务器端。)

在这种情况下,您可能还想在更改其中一个React组件时自动重新加载服务器。 你用piping包做这个。 所有你需要做的就是安装它并在server.js的开始处添加require("piping")({hook: true}) 。 而已。 更改其使用的任何组件后,服务器将重新启动。

这又引发了另外一个问题 – 如果你从Express服务器的相同进程运行webpack服务器(如上面的回答),webpack服务器也会重启,并且每次都会重新编译你的bundle。 为避免这种情况,您应该在不同的进程中运行主服务器和webpack服务器,以便pipe道系统只会重启您的快速服务器,而不会触及webpack。 你可以用concurrently包装来做到这一点。 你可以在react-isomorphic-starterkit中find这个例子。 在package.json中他有:

 "scripts": { ... "watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'" }, 

它同时运行两个服务器,但在不同的进程中。

如果您使用CLI运行webpack-dev-server,则可以通过传递devServer对象的webpack.config.js进行configuration:

 module.exports = { entry: "index.js", output: { filename: "bundle.js" }, devServer: { historyApiFallback: true } } 

historyApiFallback也可以是一个对象,而不是一个包含路由的布尔值。

 historyApiFallback: navData && { rewrites: [ { from: /route-1-regex/, to: 'route-1-example.html' } ] } 

可能并非所有情况下,但似乎是publicPath: '/'publicPath: '/'选项是解决深层路由问题的最简单的解决scheme,请参阅: https : //github.com/ReactTraining/react-router/issues/676

这工作对我来说:只需简单地添加webpack中间件和app.get('*'... index.htmlparsing器稍后,

所以expression式会首先检查请求是否与webpack提供的路由匹配(如: /dist/bundle.js/__webpack_hmr_ ),如果不/__webpack_hmr_ ,那么它将通过* resolver移动到index.html

即:

 app.use(require('webpack-dev-middleware')(compiler, { publicPath: webpackConfig.output.publicPath, })) app.use(require('webpack-hot-middleware')(compiler)) app.get('*', function(req, res) { sendSomeHtml(res) })