react-router设置path无效,错误信息Cannot GET /xxx

本文介绍了在使用webpack-dev-server时遇到Cannot GET /xxx错误和404问题的解决方案。主要涉及BrowserRouter更换为HashRouter、配置historyApiFallback以及设置publicPath。解释了historyApiFallback的作用是将404重定向至index.html,以及publicPath对引用资源路径的影响。通过调整这些设置,确保了页面的正常访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要解决了以下几个问题:
webpack-dev-server配置后,访问页面出现GET /xxx时如何解决

webpack-dev-server中historyApiFallback的作用

为什么不正确的配置会导致页面404

webpack-dev-server中publicPath的作用

为了写react demo,搭了一个简洁版的环境,因此webpack配置极其简单:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    mode: "development",
    entry: {
        app: path.join(__dirname, "../app/index.js")
    },
    output: {
        filename: "app.js",
        path: path.join(__dirname, "../dist")
    },
    resolve: {
        extensions: [".js", ".jsx"]
    },
    module: {
        rules: [
            {
                test: /\.js[x]?$/,
                use: "babel-loader"
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "../app/template.html"),
            filename: "index.html"
        })
    ],
    devServer: {
        host: "0.0.0.0",
        port: 5566
    }
}

写了个首页,访问之后,页面ok,路由如下:

<BrowserRouter>
	<Switch>
		<Route exact path="/" component={ Home } />
	</Switch>
</BrowserRouter>

然后又写了个列表页:

<Route exact path="/list" component={ List } />

但是却发现页面无法访问,页面报错信息为:Cannot GET /list。网上搜索了解决方案,主要有两个:

方法一: 将BrowserRouter更换为HashRouter
方法二: webpack中devServer添加historyApiFallback: true的配置
但是为什么这样配置就可以解决访问呢?

首先,看下webpack官网上关于historyApiFallback的说明:当使用HTML5 Histroy API时,任意的404响应都可能需要被替代为index.html,通过historyApiFallback: true启用。意思就是说,任意404响应都表现为直接渲染为http://localhost:5566/index.html,因为经过webpack打包后,在渲染模版中会引入打包后的js文件,上面设置了template输出文件名为index.html,所以在index.html文件中会引入<script type="text/javascript" src="app.js"></script>,查找页面的逻辑在js文件中。所有如果我们将模版文件的输出文件名换成其它,那么页面还是404,如:

...
plugins: [
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "../app/template.html"),
            filename: "test.html"
        })
    ]
...

如果这样设置,那么即使在devServer中添加了historyApiFallback: true的配置,访问http://localhost:5566/list时,页面仍然会显示Cannot GET /list。因为当404时,访问所有地址都会去渲染页面http://localhost:5566/index.html,但是在打包文件找不到该文件,它显示是http://localhost:5566/test.html,如果还想要访问的话,可以再将historyApiFallback进行修改:

historyApiFallback: {
	index: "/test.html"
}

更多设置可反问webpack官网

下面我们再来解决一个最重要的问题,为什么一开始的配置,访问页面的时候会404?

stackoverflow上有个回答很详细。

首先,要知道有一个服务端渲染客户端渲染的概念。其它,还需要知道,webpack-dev-server实质是提供了一个简单的web服务器本质上是一个小型的Node.js Express服务器。那么使用webpack-dev-server后,访问页面实际上走的是一个服务端渲染的过程,如果最后找不到要渲染的内容,那么就会报404。

方法一中将BrowserRouter改为HashRouter,页面的url就变成http://localhost:5566/#/xxx的形式,在hash标识(#)后的部分不会被发送到服务器端,服务器只接收到http://localhost:5566,返回首页以及包含React、React-Router的js代码,而访问其它页面时,走的是客户端渲染。

好了,现在通过设置historyApiFallback为true,解决了页面无法访问的问题。然后我想要价格列表详情页,如果如下:

<Route exact path="/list/detai" component={ Detail } />

然后发现页面又不能访问了,浏览器报错404:GET http://localhost:5566/list/app.js 404 (Not Found)。这又是为什么呢?经过资料查找,发现webpack的output中有一个配置项publicPath需要注意。publicPath指定在浏览器中所引用的「此输出目录对应的公开URL」,默认值为一个空字符串""。也就是说,如果不设置这个值,那么在模版文件(index.html)中引入的js文件地址为:

<script src="app.js"></script>

所有,当页面访问http://localhost:5566/list/detail时,其中引用的js文件为http://localhost:5566/list/aap.js,而这个文件是不存在的,因为内存中这个文件和模版文件(index.html)都在dist的根目录下。因此,为了解决这一问题,需要手动设置publicPath的值:pulicPath: "/",这个模版文件(index.html)中引入的js文件地址为:

<script src="/app.js"></script>

当页面访问http://localhost:5566/list/detail时,其中引用的js文件为http://localhost:5566/aap.js

至此,在该环境下的页面,都能正常访问了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值