解决Nginx配置React上线项目不能刷新问题

问题场景

基于React构建的单页应用中,我使用react-Router中的BrowserRouter完成页面跳转功能。打包上传至服务器,使用nginx配置时跳转路由无法刷新。例如,https://example.com 作为应用入口的话,跳转至 https://example.com/Home 后无法刷新,报错为nginx 404界面。 打包文件在/home/front/upload下,

nginx 配置如下:

原因

React-Router 实现BrowserRouter路由跳转基于history,假设当我们点击导航栏上的按钮,初始页面 https://example.com 跳转至 https://example.com/Home。这个过程是由浏览器来完成的。但是,点击刷新按钮,浏览器会进行一次导航,访问https://example.com/Home时,这个请求最终会到达nginxnginx匹配location时找不到/Home(也就是说nginx认为没有/Home这个资源,实际上也是如此),从而返回404页面。

  • 在 SPA 即单页面应用里,当用户与浏览器的后退按钮交互时,并没有真正导航到新的 HTML 页面。 而是在 window.onpopstate 上与 history.pushStatehistory.replaceState 等 API 进行交互。注意 window.onpopstate 只会在浏览器前进、后退时触发,点击刷新按钮完成的是一次导航过程,会按照路径发送真实的资源请求。现代浏览器在访问SPA应用时使用Back-Forward CacheHTML,Css,JS等资源暂存起来。用户进行页面跳转的时候,浏览器可以不必再次解析HTML、Css、JS等资源。前端只需要Ajax获取数据,使用连接抓取对象存储服务上的资源即可。

解决方案1:nginx配置try_files规则

增加如下的try_files规则

nginx官网对try_files的解释如下:docs.nginx.com/nginx/admin...

  • try_files try_files 指令可用于检查指定的文件或目录是否存在;如果存在,NGINX 会进行内部重定向;如果不存在,则返回指定的状态代码。

  • 文件以 URI 的形式指定,并使用在当前位置或虚拟服务器上下文中设置的根指令或别名指令进行处理。在这种情况下,如果与原始 URI 相对应的文件不存在,NGINX 会内部重定向到最后一个参数指定的 URI。

这样配置之后,我们的刷新请求会被内部重定向到react应用的/Home路由下,最后nginx转发这次请求的回复报文给用户。 这样刷新后,html,cssjs会重新加载

解决方案2:使用哈希路由

哈希路由,形如https://example.com/path/#/aaa/bbb,将一部分路径使用#拼接在真实路由的后面,当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange 事件。

实际上哈希路由最开始是作为锚点应用在页面中的,目的是对文档、协议书等长页面的词条进行定位和跳转的机制,后来被用作SPA应用,通过onhashchange 事件,判断当前url下哪一个组件应该被渲染,从而实现页面的跳转,实际上是一种页面组件的切换。

浏览器使用哈希路由发起导航时,hash模式下仅hash符号之前的内容会被包含在http请求中,如https://example.com/path/#/aaa/bbb,那么浏览器会对https://example.com/path/发起请求,得到页面后,再根据哈希路由完成定位和页面展示。这样在之前的例子中,我们将Home页面放到 https://example.com/#/Home下,刷新页面时,nginx收到的请求为https://example.com/,能够通过配置的location返回页面到前端,后续的页面展示由前端完成,因此解决了返回404错误的问题。

不只是React-Router,对Vue-Router也是同理。

链接

react.js application showing 404 not found in nginx server stackoverflow.com/questions/4...

Trying Several Options docs.nginx.com/nginx/admin...

浅谈前端路由原理hash和history juejin.cn/post/699384...

Vue/React 项目部署到服务器后,刷新页面出现404报错 blog.csdn.net/weixin_7331...

相关推荐
早點睡3907 小时前
高级进阶 ReactNative for Harmony 项目鸿蒙化三方库集成实战:react-native-drag-sort
react native·react.js·harmonyos
C澒7 小时前
Vue 项目渐进式迁移 React:组件库接入与跨框架协同技术方案
前端·vue.js·react.js·架构·系统架构
发现一只大呆瓜8 小时前
虚拟列表:从定高到动态高度的 Vue 3 & React 满分实现
前端·vue.js·react.js
全栈探索者9 小时前
列表渲染不用 map,用 ForEach!—— React 开发者的鸿蒙入门指南(第 4 期)
react.js·harmonyos·arkts·foreach·列表渲染
程序员Agions10 小时前
useMemo、useCallback、React.memo,可能真的要删了
前端·react.js
NEXT0610 小时前
React Hooks 进阶:useState与useEffect的深度理解
前端·javascript·react.js
早點睡39012 小时前
基础入门 React Native 鸿蒙跨平台开发:react-native-flash-message 消息提示三方库适配
react native·react.js·harmonyos
早點睡39013 小时前
高级进阶 ReactNative for Harmony项目鸿蒙化三方库集成实战:react-native-image-picker(打开手机相册)
react native·react.js·harmonyos
早點睡39013 小时前
基础入门 React Native 鸿蒙跨平台开发:react-native-easy-toast三方库适配
react native·react.js·harmonyos
●VON1 天前
React Native for OpenHarmony:2048 小游戏的开发与跨平台适配实践
javascript·学习·react native·react.js·von