index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Basic</title>
</head>
<body>
<div id="root"></div>
<script src="index.bundle.js"></script>
</body>
</html>
index.js:
import React from 'react';
import ReactDom from 'react-dom';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
// Some folks find value in a centralized route config.
// A route config is just data. React is great at mapping
// data into components, and <Route> is a component.
////////////////////////////////////////////////////////////
// first our route components
const Main = () => <h2>Main</h2>
const Sandwiches = () => <h2>Sandwiches</h2>
const Tacos = ({ routes }) => (
<div>
<h2>Tacos</h2>
<ul>
<li><Link to="/tacos/bus">Bus</Link></li>
<li><Link to="/tacos/cart">Cart</Link></li>
</ul>
{routes.map((route, i) => (
<RouteWithSubRoutes key={i} {...route} />
))}
</div>
)
const Bus = () => <h3>Bus</h3>
const Cart = () => <h3>Cart</h3>
////////////////////////////////////////////////////////////
// then our route config
const routes = [
{
path: '/sandwiches',
component: Sandwiches
},
{
path: '/tacos',
component: Tacos,
routes: [
{
path: '/tacos/bus',
component: Bus
},
{
path: '/tacos/cart',
component: Cart
}
]
}
]
// wrap <Route> and use this everywhere instead, then when
// sub routes are added to any route it'll work
const RouteWithSubRoutes = (route) => (
<Route path={route.path} render={props => (
// pass the sub-routes down to keep nesting
<route.component {...props} routes={route.routes} />
)} />
)
const RouteConfigExample = () => (
<Router>
<div>
<ul>
<li><Link to="/tacos">Tacos</Link></li>
<li><Link to="/sandwiches">Sandwiches</Link></li>
</ul>
{routes.map((route, i) => (
<RouteWithSubRoutes key={i} {...route} />
))}
</div>
</Router>
)
ReactDom.render(
<RouteConfigExample />,
document.getElementById('root')
);
webpack.config.js:
var path = require('path');
module.exports = {
entry: {
index: './index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, '/'),
publicPath: '/',
},
module: {
rules: [
{
test: /\.js[x]?$/,
exclude: /(node_modules)/,
use: [{
loader: "babel-loader",
options: {
presets: ["react", "es2015", "stage-0"],
plugins: []
}
}]
},
]
},
devServer: {
contentBase: path.join(__dirname, '/'),
compress: true,
port: 9000,
watchContentBase: true,
watchOptions: {
poll: true
},
historyApiFallback: true,
historyApiFallback: {
// rewrites: [
// { from: /^\/tacos/, to: '/index.html' },
// ],
index: '/index.html',
},
proxy: {
"/tacos/bus": {
target: "http://localhost:9000",
pathRewrite: { '^/tacos': '' },
}
},
}
};
my routes path have four: /tacos , /sandwiches , /tacos/bus , /tacos/cart .
when the route path is /tacos or /sandwiches , I refresh is ok , but when /tacos/bus and /tacos/cart , got 404 , and I try to proxy my index.bundle.js , but it doesn't work, and I found that 404 url is http://localhost:9000/tacos/index.bundle.js , the correct url should be http://localhost:9000/index.bundle.js . I don't kown the reason , and how to solve that, please?
Hi!
Does it work if you just set historyApiFallback to true, and remove the proxy?
It's the problem with the src path:
<script src="index.bundle.js"></script>
I write to that and then it worked:
<script src="/index.bundle.js"></script>
@RifeWang, your answer above just helped me solve my react router nested routes issue that I've been fighting for a day or two now. Thank you so much!
im having this very same issue.
@apeg1515 please void posting "me too" or "same issue" comments. instead, please use the reaction buttons on the original issue or comment you agree with or want to support.
sorry about the @shellscape . my issues was that I didn't give webpack a "out.publicPath". I did include some of the recommended solutions up above but I haven't test it in particular to verify that it actually works. The 'out.publicPath" fixed it for me.
I had the same problem! it seems that the line historyApiFallback: true inside devServer saved the day
But what about if webpack generates the html and javascript in-memory, with HtmlWebpackPluginConfig? How to remove the relative path of the script, then?
[EDIT]: adding the 'publicPath' key inside the 'output' object inside the export object inside the webpack.config.js file worked for me:
{
...
output: {
...
publicPath: '/'
}
}
For me
historyApiFallback: true works.
not
publicPath: '/'.
I think it is because the refreshing in deeper route(e.g. /about) is requesting the index.html (i.e. /about/index.html) but got none.
Edit:
However, I got Refused to execute script from 'http://localhost:8090/topics/bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled. when I refresh in "http://localhost:9000/topics/components" if I don't set `publicPath: '/'.`.
With both, project is working properly.
I'm trying to serve from the /build folder using github pages.
I'm using browser router.
But every route other '/' works only initially. If I refresh it shows githubs 404 page.
There is no problem if I import HashRouter instead.
Why is that so?
What is wrong with Browser Router?
Most helpful comment
But what about if webpack generates the html and javascript in-memory, with HtmlWebpackPluginConfig? How to remove the relative path of the script, then?
[EDIT]: adding the 'publicPath' key inside the 'output' object inside the export object inside the webpack.config.js file worked for me: