假设我们现在有几个页面
-
Home页面
-
List页面
-
还有一个index.js页面,展示的是 Hello World
当我们启动服务器,页面显示的是Hello World,但是我们希望,当访问根路径 /
的时候,展示的是Home页面,而访问/list
路径的时候,展示的是List页面;要实现这种效果,在react种,我们就需要使用单页面路由
。步骤如下:
- 安装前端路由模块
npm install react-router-dom --save
- 修改index.js文件
import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom'
import ReactDom from 'react-dom';
import Home from './home.js'
import List from './list.js'
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Route path='/' exact component={Home}/>
<Route path='/list' component={List}/>
</div>
</BrowserRouter>
)
}
}
ReactDom.render(<App />, document.getElementById('root'));
- 启动服务器,可以看到,直接显示了
Home Page
- 但是当我们访问
localhost:8080/list
的时候,就会报错,找不到list页面;为什么会这样呢? 原因是当我们访问localhost:8080/list
的时候,webpack-dev-server
会以为我们访问的是后端的一个叫list
的页面,但是我们的文件夹内,只有一个index.html
这个页面,并没有list.html
这个页面,这种情况下,就会提示我们页面不存在,这也是我们做前端单页应用经常遇到的问题
那再webpack-dev-server
里,怎么解决这个问题呢?我们还是先看下wepack官网文档
-
我们直接这样配置就可以了
- 配置后,我们再重启服务器,访问
localhost:8080/list
就可以看到内容了,也就是说路由生效了
- 它的原理是,当我们配置了
historyApiFallback: true
的时候,无论我们访问的是任何一个路径,它都会默默的把对这个路径的请求转换到对根路径的请求。也就是说都会去引入我们的index.html
页面,只要引入index.html
,它引入的main.js
就会执行,而这个main.js
就是我们打包过后的代码,就是我们index.js的业务代码,所以它里面的路由就会生效
historyApiFallback 还可以配置其他的内容
1.出了上边配置一个布尔类型的值以外,它还可以配置一个 rewrites
规则,比如像下边这样的配置,意思就是吗,如果发现访问的是abc.html
那么就让页面展示list.html
,不过因为我们上边例子目录中并没有list.html
所以是访问不到的
- 我们把配置修改为,当我们访问
abc.html
,页面展示index.html
,我们的目录里是有这个文件的。会展示吗?重启后,发现也没有展示,但是查看网页源代码时发现index.html
内容展示出来了;之所以会这样,是因为index.html里有我们的业务代码,而我们的业务代码里,没有写如果访问abc.html
就显示其他的内容的逻辑
- 实际上,当我们配置了
historyApiFallback: true
的时候,就相当于这样配置;访问任何内容都会展示index.html
-
更多的配置,可以到这里去了解
注意因为historyApiFallback
是devServer
的配置,所以只在开发环境下有效。一旦到了线上环境,就可能出现页面找不到的情况,因为我们在开发环境,通过historyApiFallback
配置了跳转的规则,但是后端的服务器很有可能没有配置跳转的规则,这个问题,前端是解决不了的,需要后端的小伙伴去nginx 或者 apache
上仿照webpack-dev-server
的一些配置,去在他的对应的服务器上去做同样的配置,这样才可以在前端使用路由不会有问题;
所以,上线之前,一定要周知后端去改配置