webpack-dev-server react-router4 嵌套路由404

1、使用的是react-router 官方的 router config 例子:

import React from 'react';
import ReactDom from 'react-dom';
import {
    BrowserRouter as Router,
    Route,
    Link
} from 'react-router-dom'

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>

const routes = [
    {
        path: '/sandwiches',
        component: Sandwiches
    },
    {
        path: '/tacos',
        component: Tacos,
        routes: [
            {
                path: '/tacos/bus',
                component: Bus
            },
            {
                path: '/tacos/cart',
                component: Cart
            }
        ]
    }
]

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')
);

2、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': '/' },
            }
        },
        
    }
};

3、问题如下:

由于启用了 historyApiFallback ,路由 /tacos/sandwiches 刷新页面没有问题,bundle.js 文件的地址是 http://localhost:9000/index.bundle.js

但是嵌套的路由 /tacos/bus/tacos/cart 刷新页面之后仍然是 404 ,并且加载 bundle.js 文件的地址变成了 http://localhost:9000/tacos/index.bundle.js
试图用 proxy 去改写此地址但却无效。

另外嵌套的路由 /tacos/bus/tacos/cart似乎并没有与 /tacos/sandwiches 一样被作为一个 BrowserHistory , 不知道这个问题是 react-router 还是 webpack-dev-server 的问题?

阅读 6.2k
2 个回答

index.html中引入js文件路径的问题,相对于网站的根路径引入,不要用相对路径引入。

//不要写这个路径,不要写这个路径,不要写这个路径
<script type="text/javascript" src="index.bundle.js"></script>

//写这个路径,写这个路径,写这个路劲
<script type="text/javascript" src="/index.bundle.js"></script>

http://localhost:9000/ 是访问到你 `http://localhost:9000/index.html。这样子如果服务器不做跳转配置的话,那你访问的 /tacos/cart/tacos/bus 等于去访问了 http://localhost:9000/tacos/ 下的东西。

使用 HashRouter可以解决你的问题。缺点是对搜索引擎不友好。

具体使用方法你也可以参考我刚为 redux-form 整理的一片文章 React-Redux技术栈——之redux-form详解,里面使用了history/createHashHistory作为history管理,有代码可以下载。

react-router改版到4.x之后变化挺大的,我正着手结合官方文档整理关于react-route一些实用的demo。

推荐问题
宣传栏