我正在创建一个使用webpack-dev-server进行开发的应用程序以及react-router。
似乎webpack-dev-server是基于这样的假设:你会在一个地方(即“/”)有一个公共入口点,而react-router允许无限量的入口点。
我想要webpack-dev-server的好处,特别是热量重新加载功能,这对于提高工作效率很有帮助,但我仍然希望能够加载在react-router中设置的路由。
如何实现它以便它们一起工作?你能以这种方式在webpack-dev-server前面运行一个快速服务器吗?
答案 0 :(得分:100)
您应将historyApiFallback
的{{1}}设为true才能生效。这是一个小例子(根据您的目的进行调整):
WebpackDevServer
答案 1 :(得分:66)
我设置了一个代理来实现这个目标:
您有一个常规的快速网络服务器,可以在任何路线上为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);
现在在webpack配置中创建入口点,如下所示:
entry: [
'./src/main.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081'
]
注意直接调用8081进行hotreload
还要确保将绝对网址传递给output.publicPath
选项:
output: {
publicPath: "http://localhost:8081/assets/",
// ...
}
答案 2 :(得分:22)
对于其他可能仍在寻找此答案的人。我整理了一个简单的代理绕过,实现了这个没有太多的麻烦,配置进入webpack.config.js
我确信有更优雅的方法可以使用正则表达式测试本地内容,但这可以满足我的需求。
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';
}
}
}
}
}
答案 3 :(得分:9)
如果您使用CLI运行webpack-dev-server,可以通过webpack.config.js传递devServer对象来配置它:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js"
},
devServer: {
historyApiFallback: true
}
}

每次遇到404时,都会重定向到index.html。
注意:如果您使用的是publicPath,那么您也需要将其传递给devServer:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js",
publicPath: "admin/dashboard"
},
devServer: {
historyApiFallback: {
index: "admin/dashboard"
}
}
}

您可以通过查看输出的前几行来确认所有内容都已正确设置(带有" 404s的部分将回退到:路径")。
答案 4 :(得分:8)
对于更新的答案,当前版本的webpack(4.1.1)你可以在你的webpack.config.js中设置它,如:
const webpack = require('webpack');
module.exports = {
entry: [
'react-hot-loader/patch',
'./src/index.js'
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader','css-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true,
historyApiFallback: true
}
};
重要的部分是historyApiFallback: true
。无需运行自定义服务器,只需使用cli:
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development"
},
答案 5 :(得分:2)
当您运行同构应用程序(即呈现React组件服务器端)时,我想添加案例的答案。
在这种情况下,您可能还希望在更改其中一个React组件时自动重新加载服务器。您可以使用piping
包执行此操作。您所要做的就是安装它并在 server.js 的开头添加require("piping")({hook: true})
。而已。更改任何组件后,服务器将重新启动。
这引发了另一个问题 - 如果您从与快速服务器相同的进程运行webpack服务器(如上面接受的答案),webpack服务器也将重新启动并且每次都会重新编译您的软件包。为避免这种情况,您应该在不同的进程中运行主服务器和webpack服务器,以便管道只重新启动您的快速服务器,并且不会触及webpack。
您可以使用concurrently
包执行此操作。您可以在react-isomorphic-starterkit中找到相关示例。在 package.json 中,他有:
"scripts": {
...
"watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'"
},
同时运行两个服务器但在不同的进程中运行。
答案 6 :(得分:1)
historyApiFallback
也可以是一个对象,而不是包含路径的布尔值。
historyApiFallback: navData && {
rewrites: [
{ from: /route-1-regex/, to: 'route-1-example.html' }
]
}
答案 7 :(得分:1)
可能并非在所有情况下,但似乎devServer中的publicPath: '/'
选项是解决深层路由问题的最简单方法,请参阅:https://github.com/ReactTraining/react-router/issues/676
答案 8 :(得分:0)
这对我有用:只需先添加webpack中间件,然后再添加.wrapper {
overflow: hidden;
}
.wrapper img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* height: 100%; */ /* optional */
}
index.html解析器,
所以express会首先检查请求是否与webpack提供的路由之一匹配(例如:app.get('*'...
或/dist/bundle.js
),如果不匹配,那么它将移至/__webpack_hmr_
index.html
解析器。
即:
*