-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support webpack-dev-server historyApiFallback: true #676
Comments
This is not the router's problem: Webpack just doesn't know you're using pushstate and tries to actually serve The proper way to do that is to run pushstate server separately and set A hackish but simpler way to do that is to inject a middleware (note this relies on undocumented property and may stop working in future): server = new WebpackDevServer(webpack(config), {
contentBase: contentBase,
publicPath: config.output.publicPath,
hot: true
});
server.app.use(function pushStateHook(req, res, next) {
var ext = path.extname(req.url);
if ((ext === '' || ext === '.html') && req.url !== '/') {
req.pipe(request(localURL)).pipe(res);
} else {
next();
}
}); Can't say how to translate this to grunt task tho. |
@gaearon |
I don't know, it shouldn't. If server doesn't serve |
@gaearon well key diff in this historyApiFallback: true react-router-component works fine with this option and react-router is not ... |
I'm not sure what |
@gaearon
|
Ah, thanks. I didn't know dev server supports this. So you're saying it doesn't work with RR but works with RRC? |
@gaearon exactly |
I'll take a look, thanks for reporting! |
@gaearon do you know what the core issue is with |
I'll take a look now, sorry for delay |
I couldn't reproduce the problem. In my testing, |
I find historyApiFallback works with shallow routes but not deep routes, I'm not sure it has anything to do with react-router though. |
I found a problem there
but still RR doesn't work if you want your routes without hashes (Router.HistoryLocation)
p.s. full project with code is here https://github.com/fellz/react-webpack-app |
https://github.com/webpack/react-starter uses pushstate and the router, so something must be up with your app. Let us know if you find what's wrong :) |
I just ran into this issue. You have to tell webpack to always serve up index.html. Here is an example, assuming your server.js file and index.html are both in the root of your project: server.js var webpack = require('webpack'),
WebpackDevServer = require('webpack-dev-server'),
config = require('./webpack.config'),
path = require("path");
var server = new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
});
// Important part. Send down index.html for all requests
server.use('/', function(req, res) {
res.sendFile(path.join(__dirname+'/index.html'));
});
server.listen(3010, 'localhost', function (err, result) {
if (err) {
console.log(err);
}
console.log('Listening at localhost:3010');
}); |
If you're like me and use var config = require('./webpack.config');
var http = require('http');
var path = require('path');
var url = require('url');
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var server = new WebpackDevServer(webpack(config), config.devServer);
// Important part. Send down index.html for all requests
server.use('/', function (req, resp, next) {
var opts = url.parse('http://localhost:8080');
opts.method = req.method;
opts.headers = req.headers;
var myReq = http.request(opts, function (myRes) {
var statusCode = myRes.statusCode;
var headers = myRes.headers;
var location = headers.location;
if (200 !== statusCode) {
next();
return;
}
resp.writeHead(myRes.statusCode, myRes.headers);
myRes.on('error', function (err) {
next(err);
});
myRes.pipe(resp);
});
myReq.on('error', function (err) {
next(err);
});
if (!req.readable) {
myReq.end();
} else {
req.pipe(myReq);
}
});
server.listen(8080, 'localhost', function() {
console.log('Listening on http://localhost:' + server.get('port'));
}); |
@nelix I ran into a similar issue. I am not yet using react-router, but the symptom matched to what is being described here. In my case, setting |
Thanks @ramnivas |
Some of the examples above are very complicated. In most cases you can get this working simply by adding the following lines to your
I made an example app to help anyone else looking for a solution to this (like I was). |
@adrianmacneil seems that react's about "complexity first" sometimes (: |
@adrianmacneil As mentioned above, that only seems to work for shallow routes. For example, it will work for |
It works fine for me with nested routes. Try the example app above - I just added a nested route to test it. |
@dmwyatt, 👍 on that. I've got a simple case that success for one level deep, but fails beyond that. (Any chance you're lazy-loading files with |
@michaelahlers No, I'm not using
With this config my app is now finally loading all routes...but it does a complete page load for each route transition unless I switch to hash routes. |
@adrianmacneil's solution worked for me. :-) |
I've been struggling with this for longer than I'd like to admit, but I've just figured it out. Besides enabling In my case, it was the difference between Thanks to @adrianmacneil for the sample app, it was a big help. edit - "/bundle.js" being the correct src, so the reference isn't taken as relative to the current path. |
@BenFlanagan thanks a lot. Completely agree with it:
|
@dmwyatt or anybody else, did you find a way to stop the complete page load every time the route changes ? |
In addition to @BenFlanagan's excellent observation:
When using the HTML Webpack Plugin to generate your bootstrap page, you'll be able to enforce absolute paths by adding a {
// ...
output: {
// ...
publicPath: '/',
// ...
}
// ...
} Incidentally, this should be useful for those encountering issue #113 in react-boilerplate. |
@BenFlanagan Adding that single slash fixed a running 2 month bug we had with (only) our nested routes and hot-reloading. Thank you so much! |
@BenFlanagan That was it for me :) |
@michaelahlers and @BenFlanagan summed up solved the issue here. |
👍 |
@xuorig, I'm still struggling with full page reload on route navigation. Have you succeeded to solve it? Any ideas how that can be fixed? |
@Dmitry-N-Medvedev don't know if it's your case but if you have modified the output.publicPath you should specify the redirect URL. // output.publicPath: '/foo-app/'
historyApiFallback: {
index: '/foo-app/'
} |
@BenFlanagan solved this problem for me. But then I had issues resolving some of my static resources. I added |
@dmwyatt did you fix the problem with nested urls? i fixed it with publicPath but now reloads full page instead components :'( |
const path = require('path');
const fs = require("fs");
{
devServer: {
historyApiFallback: false,
setup: function (app) {
app.use(function pushStateHook(req, res, next) {
var ext = path.extname(req.url);
if ((ext === '' || ext === '.html') && req.url !== '/') {
res.setHeader("Content-Type", "text/html");
fs.createReadStream(helpers.root('dist-dev/index.html')).pipe(res);
} else {
next();
}
});
}
}
} |
This issue comes up in google a lot, so this might come in handy to anyone having trouble with this: I don't know how to fix it other than to remove the |
Hi
I don't know exactly is this issue with webpack but i think so
I have simple config for router
So i try to load HelloWorld component at /hello and get Cannot GET /hello
So server doesn't see this route
I use grunt and connect also.
Here is grunt task for webpack:
and here is webpack config
https://gist.github.com/fellz/b2cc0de81c7b1f5bf442#file-webpack-config
with historyApiFallback: true
it's loading ReactappApp instead of HelloWorld
p.s. react-router-component works as expected and perfectly well
The text was updated successfully, but these errors were encountered: