Javascript 如何允许 webpack-dev-server 允许来自 react-router 的入口点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26203725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to allow for webpack-dev-server to allow entry points from react-router
提问by Nathan Wienert
I'm creating an app that uses webpack-dev-server in development alongside react-router.
我正在创建一个在开发中使用 webpack-dev-server 和 react-router 的应用程序。
It seems that webpack-dev-server is built around the assumption that you will have a public entry point at one place (i.e. "/"), whereas react-router allows for an unlimited amount of entry points.
似乎 webpack-dev-server 是围绕这样一个假设构建的,即您将在一个地方(即“/”)有一个公共入口点,而 react-router 允许无限数量的入口点。
I want the benefits of the webpack-dev-server, especially the hot reloading feature that is great for productivity, but I still want to be able to load routes set in react-router.
我想要 webpack-dev-server 的好处,尤其是对生产力很有帮助的热重载功能,但我仍然希望能够加载 react-router 中设置的路由。
How could one implement it such that they work together? Could you run an express server in front of webpack-dev-server in such a way to allow this?
怎样才能实现它,让他们一起工作?你能在 webpack-dev-server 前面运行一个快速服务器以允许这样做吗?
采纳答案by Retozi
I set up a proxy to achieve this:
我设置了一个代理来实现这一点:
You have a regular express webserver that serves the index.html on any route, except if its an asset route. if it is an asset, the request gets proxied to the web-dev-server
您有一个常规快速网络服务器,可以在任何路由上提供 index.html,除非它是资产路由。如果它是资产,则请求会被代理到 web-dev-server
your react hot entrypoints will still point directly at the webpack dev server, so hot reloading still works.
你的 react hot 入口点仍然会直接指向 webpack 开发服务器,所以热重载仍然有效。
Let's assume you run webpack-dev-server on 8081 and your proxy at 8080. Your server.js file will look like this:
假设您在 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);
now make your entrypoints in the webpack config like so:
现在在 webpack 配置中创建入口点,如下所示:
entry: [
'./src/main.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081'
]
note the direct call to 8081 for hotreload
请注意直接拨打 8081 进行 hotreload
also make sure you pass an absolute url to the output.publicPathoption:
还要确保您将绝对网址传递给该output.publicPath选项:
output: {
publicPath: "http://localhost:8081/assets/",
// ...
}
回答by Juho Veps?l?inen
You should set historyApiFallbackof WebpackDevServeras true for this to work. Here's a small example (tweak to fit your purposes):
你应该设置historyApiFallback的WebpackDevServer这个作为真正的工作。这是一个小示例(根据您的目的进行调整):
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);
});
回答by Werner Weber
For anyone else that may still be looking for this answer. I put together a simple proxy bypass which achieves this without much hassle and the config goes into the webpack.config.js
对于可能仍在寻找此答案的其他任何人。我整理了一个简单的代理绕过,它可以轻松实现这一点,并且配置进入 webpack.config.js
I am sure there are much more elegant ways to test for local content using regex, but this works for my needs.
我确信有更优雅的方法来使用正则表达式测试本地内容,但这适合我的需要。
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';
}
}
}
}
}
回答by Eugene Kulabuhov
If you're running webpack-dev-server using CLI, you can configure it through webpack.config.js passing devServer object:
如果你使用 CLI 运行 webpack-dev-server,你可以通过 webpack.config.js 传递 devServer 对象来配置它:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js"
},
devServer: {
historyApiFallback: true
}
}
This will redirect to index.html everytime it 404 is encountered.
这将在每次遇到 404 时重定向到 index.html。
NOTE: If you're using publicPath, you'll need to pass it to devServer too:
注意:如果您使用的是 publicPath,则还需要将其传递给 devServer:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js",
publicPath: "admin/dashboard"
},
devServer: {
historyApiFallback: {
index: "admin/dashboard"
}
}
}
You can verify that everything is setup correctly by looking at the first few lines of the output (the part with "404s will fallback to: path").
您可以通过查看输出的前几行来验证一切设置是否正确(带有“404s 将回退到:路径”的部分)。
回答by Michael Brown
For a more recent answer, the current version of webpack (4.1.1) you can just set this in your webpack.config.js like such:
对于最近的答案,当前版本的 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
}
};
The important part is historyApiFallback: true. No need to run a custom server, just use the cli:
重要的部分是historyApiFallback: true。无需运行自定义服务器,只需使用 cli:
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development"
},
回答by Viacheslav
I'd like to add to the answer for the case when you run an isomorphic app (i.e. rendering React component server-side.)
当您运行同构应用程序(即在服务器端呈现 React 组件)时,我想为案例添加答案。
In this case you probably also want to automatically reload the server when you change one of your React components. You do this with the pipingpackage. All you have to do is install it and add require("piping")({hook: true})somewhere in the beginning of you server.js. That's it. The server will restart after you change any component used by it.
在这种情况下,您可能还希望在更改 React 组件之一时自动重新加载服务器。你用piping包来做这件事。您所要做的就是安装它并require("piping")({hook: true})在server.js的开头添加某处。就是这样。服务器将在您更改它使用的任何组件后重新启动。
This rises another problem though - if you run webpack server from the same process as your express server (as in the accepted answer above), the webpack server will also restart and will recompile your bundle every time. To avoid this you should run your main server and webpack server in different processes so that piping would restart only your express server and won't touch webpack.
You can do this with concurrentlypackage. You can find an example of this in react-isomorphic-starterkit. In the package.jsonhe has:
不过,这会带来另一个问题 - 如果您从与 express 服务器相同的进程中运行 webpack 服务器(如上面接受的答案),webpack 服务器也会重新启动,并且每次都会重新编译您的包。为了避免这种情况,你应该在不同的进程中运行你的主服务器和 webpack 服务器,这样管道只会重新启动你的 express 服务器并且不会接触 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'"
},
which runs both servers simultaneously but in separate processes.
它同时运行两个服务器,但在不同的进程中。
回答by Tom Roggero
historyApiFallbackcan also be an object instead of a Boolean, containing the routes.
historyApiFallback也可以是一个包含路由的对象而不是布尔值。
historyApiFallback: navData && {
rewrites: [
{ from: /route-1-regex/, to: 'route-1-example.html' }
]
}
回答by Alex
May be not in all cases, but seems the publicPath: '/'option in the devServer is easiest solution to fix deep routes issue, see: https://github.com/ReactTraining/react-router/issues/676
可能并非在所有情况下,但似乎publicPath: '/'devServer 中的选项是修复深度路由问题的最简单解决方案,请参阅:https: //github.com/ReactTraining/react-router/issues/676
回答by Graham Norton
This worked for me: just simply add the webpack middlewares first and the app.get('*'...index.html resolver later,
这对我有用:只需先添加 webpack 中间件,然后再添加app.get('*'...index.html 解析器,
so express will first check if the request matches one of the routes provided by webpack (like: /dist/bundle.jsor /__webpack_hmr_) and if not, then it will move to the index.htmlwith the *resolver.
所以表示将首先检查该请求是否匹配由的WebPack(如:所提供的路线之一/dist/bundle.js或/__webpack_hmr_),并且如果没有,那么它会移动到index.html与所述*解析器。
ie:
IE:
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)
})


