React作品集网站部署后Contact Form刷新出现404 NotFound问题
React SPA部署后刷新非根路径出现404问题解决
问题描述
开发React作品集网站,本地运行正常,部署到线上服务器后出现异常:提交Contact Form并刷新页面时,浏览器控制台提示GET 404 - NOT FOUND,URL保持不变但无法访问,且该路径已在React Router中配置,当前使用emailjs实现表单发送功能。
相关代码
ContactForm组件
import React from 'react'; import { useRef } from 'react'; import './contactForm.css'; import { Footer } from '../../containers'; import emailjs from '@emailjs/browser'; const ContactForm = () => { const form = useRef(); const sendEmail = (e) => { e.preventDefault(); emailjs.sendForm('service_ebesa9d', 'template_846mobc', form.current, '1oviDjIxcKzRsgPPd') .then((result) => { console.log(result.text); console.log("message sent"); alert("Message sent succesfully"); // window.location.reload(false); }, (error) => { console.log(error.text); alert("Oops, something went wrong"); }); }; return ( <div className='RO__ContactForm' id='contactForm'> <div className='RO__ContactForm-title'> <h3>Contact</h3> <h1>I'm here to help you level up</h1> </div> <div className='RO__ContactForm-content'> <div className='RO__ContactForm-content_description'> <p>I'm just on click away to help you take your company to the next level. Fill in the form to share more details about the project or your favorite movie. Either way, I'd love to talk.</p> </div> <form className='RO__ContactForm-content_form' ref={form} onSubmit={sendEmail} > <div className='RO__ContactForm-content_form_name'> <div className='RO__ContactForm-content_form_nameTitle'> <h5>What's your name?</h5> </div> <input className='RO_ContactForm-content_form_nameInput' type= 'text' id='user_name' name='user_name' required /> </div> <div className='RO__ContactForm-content_form_email'> <div className='RO__ContactForm-content_form_emailTitle'> <h5>Your email</h5> </div> <input className='RO__ContactForm-content_form_emailInput' type='email' id='user_email' name='user_email' required /> </div> <div className='RO__ContactForm-content_form_info'> <div className='RO__ContactForm-content_form_infoTitle'> <h5>What can I help you with?</h5> </div> <textarea className='RO__ContactForm-content_form_infoContent' id='message' name='message' required /> </div> <div className='RO__ContactForm-content_form_button'> <button type='submit' value='send' > Submit </button> </div> </form> </div> <div className='RO__ContactForm-footer'> <Footer /> </div> </div> ); } export default ContactForm
路由配置
import React from 'react'; import { Routes, Route } from 'react-router-dom'; import { Footer, About, Features, Services, Header, Portfolio, Contact } from './containers'; import { Article, Brand, Cta, Feature, Navbar, ScrollToTop } from './components'; import { Project1, Project2, Project3, Project4, Project5, Project6, Project7 } from './pages' import { ContactForm } from './pages/contactform'; import './App.css'; const App = () => { return ( <Routes> <Route path='/' element={ <div className = "App"> <div className='gradient__bg'> <Navbar /> <Header /> </div> <About /> <Services /> <Portfolio /> <Contact /> <Footer /> </div> } /> <Route path='/project1' element = {<Project1 />} /> <Route path='/project2' element = {<Project2 />} /> <Route path='/project3' element = {<Project3 />} /> <Route path='/project4' element = {<Project4 />} /> <Route path='/project5' element = {<Project5 />} /> <Route path='/project6' element = {<Project6 />} /> <Route path='/project7' element = {<Project7 />} /> <Route path='/contactForm' element = {<ContactForm />} /> <Route path='/services' element = {<Services />} /> </Routes> ) } export default App
问题原因
这是单页应用(SPA)部署的典型问题:
- 本地开发时,React开发服务器会拦截所有路由请求,统一转发到
index.html,由React Router在客户端处理路由匹配。 - 线上服务器默认会根据URL路径查找对应的物理文件,而SPA只有一个
index.html,当刷新非根路径(如/contactForm)时,服务器找不到对应文件,返回404。
解决方案
1. 配置服务器重写规则(以Nginx为例)
修改Nginx配置文件,添加try_files指令,将所有请求转发到index.html:
server { listen 80; server_name your-domain.com; root /path/to/your/build/folder; # 替换为你的项目build目录路径 index index.html; location / { try_files $uri $uri/ /index.html; # 优先找物理文件,找不到就返回index.html } }
修改后重启Nginx服务生效。
2. 托管平台(Netlify/Vercel)配置
如果部署在Netlify、Vercel这类静态托管平台,无需修改服务器配置,只需添加路由重写规则:
- Netlify:在项目根目录创建
_redirects文件,内容如下:/* /index.html 200 - Vercel:在项目根目录创建
vercel.json文件,内容如下:{ "rewrites": [ { "source": "/(.*)", "destination": "/index.html" } ] }
将文件提交到代码仓库,平台会自动应用规则。
3. 切换React Router为Hash模式
如果不想修改服务器或平台配置,可以将BrowserRouter替换为HashRouter,这种模式会在URL中添加#,所有路由请求都由客户端处理,不会触发服务器的物理文件查找:
import { HashRouter, Routes, Route } from 'react-router-dom'; const App = () => { return ( <HashRouter> <Routes> {/* 原有的所有路由配置 */} <Route path='/' element={...} /> <Route path='/contactForm' element={<ContactForm />} /> {/* 其他路由 */} </Routes> </HashRouter> ) }
注意:此方法会改变URL格式(如/contactForm变为/#/contactForm),如果对URL美观性有要求,优先选择前两种方案。
内容的提问来源于stack exchange,提问作者Rafael Oliva
相关产品推荐
相关产品推荐

