1. 背景
团队的前端使用 React + React Router 开发单页应用(SPA),特别影响用户体验的一个痛点是:
- 浏览器刷新当前页面,提示 404
- 点击浏览器历史记录,提示 404
- 输入 URL,提示 404
Linux + Nginx 环境前端团队找到了解决方案,在 nginx.conf 添加如下代码即可:
location ~ /xxx/ {
if ($request_uri ~* ^([^.]+|.*\.html)$){
proxy_pass http://$proxy_ip/xxx-lk/index.html;
}
root /opt/wwwroot/;
index /xxx/index.html;
}
location ~ /xxx-lk/ {
root /opt/wwwroot/;
index /xxx/index.html;
}
}
即将上线的项目,客户使用 Windows 服务器,我们不得不在 IIS 完成同样的配置……
2. 路由原理
2.1. Server side
传统的 B/S 开发,在浏览器地址栏输入 http://example.com/about 后,浏览器请求 example.com 服务器,服务器接收请求之后解析 URL 得到 about,向浏览器发送「关于我们」页面。
2.2. Client side
使用客户端路由时,在浏览器地址栏输入 http://example.com/about 后:
- 向服务器
example.com发起请求,服务端路由找不到/about,默认返回包含所需资源的页面index.html。 - 浏览器加载 React 和 React Router,路由初始化成功,将
/about指向About us组件(Component)。 - 浏览器 URL 为
http://example.com/about,客户端路由导航显示About us组件,隐藏其他组件。
2.3. React Router
React Router 是建立在 history 之上的,history 监听浏览器地址栏的变化并解析 URL 转化为 location 对象,然后 router 使用它匹配到路由,正确地渲染对应的组件。
常用的 history 有三种形式:
- browserHistory
- hashHistory
- createMemoryHistory
使用 React Router 时推荐用 Browser history,它使用浏览器的 History API 处理 URL,创建类似于 http://example.com/about 这样真实的 URL。
3. 解决方案
3.1. IIS
web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React-Router" stopProcessing="true">
<match url="^xxx/(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="xxx/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
3.2. Nginx
nginx.conf
location /xxx {
try_files $uri $uri/ /xxx/index.html;
}