如何用React和Express处理动态404页面及404状态码(含SSR场景)
React中处理404页面与正确状态码的方案
1. 客户端渲染(SPA)场景:修复404页面状态码为200的问题
纯客户端渲染的React应用里,浏览器的HTTP状态码由首次请求的服务器响应决定。如果用户直接访问未定义的路由,服务器通常会返回index.html(状态码200),之后客户端路由才渲染NotFound页面,导致状态码显示异常。解决这个问题需要服务器端配合:
服务器端路由校验配置
配置你的服务器(Nginx、Express等),只对React应用中定义的有效路由返回index.html;未匹配的路由直接返回404状态码和自定义NotFound页面。
Express示例:
const path = require('path'); const express = require('express'); const app = express(); // 定义所有有效客户端路由 const validRoutes = ['/', '/about', '/products']; app.use(express.static(path.join(__dirname, 'build'))); app.get('*', (req, res) => { if (validRoutes.includes(req.path)) { res.sendFile(path.resolve(__dirname, 'build', 'index.html')); } else { // 返回404状态码和NotFound页面 res.status(404).sendFile(path.resolve(__dirname, 'build', '404.html')); } }); app.listen(3000);
客户端补充处理:
如果用户是从有效路由内部跳转到无效路由(客户端导航),浏览器不会发送新的HTTP请求,状态码仍为200。这种情况下,可以通过修改页面标题、添加明确的404提示,或加入meta标签帮助搜索引擎识别:
import { useEffect } from 'react'; function NotFound() { useEffect(() => { document.title = '404 - 页面不存在'; }, []); return ( <div> <meta name="robots" content="noindex, nofollow" /> <h1>404 - 页面不存在</h1> </div> ); }
2. SSR/预渲染场景:让404页面返回真实404状态码
无论是使用Next.js、Gatsby这类框架,还是自定义SSR服务,核心是在渲染阶段判断路由有效性,无效则设置响应状态码为404。
Next.js示例(支持SSR/SSG)
- SSR场景(getServerSideProps):
创建pages/[...notFound].js捕获所有未匹配路由:
export async function getServerSideProps(context) { // 自定义逻辑:校验当前路由是否有效 const isValidRoute = checkValidRoute(context.resolvedUrl); if (!isValidRoute) { // 设置响应状态码为404 context.res.statusCode = 404; } return { props: {} }; } export default function NotFound() { return <h1>404 - 页面不存在</h1>; }
- 静态预渲染(SSG)场景:
通过getStaticPaths声明所有有效路由,未包含的路由会自动触发404:
export async function getStaticPaths() { // 获取所有有效路由(比如从CMS或数据库拉取) const validPaths = await fetchAllValidRoutes(); return { paths: validPaths.map(path => ({ params: { slug: path } })), fallback: 'blocking' // 未定义的路由会返回404 }; } export async function getStaticProps(context) { const isValid = checkValidRoute(context.params.slug); if (!isValid) { return { notFound: true }; // Next.js自动返回404状态码 } return { props: {} }; }
自定义SSR服务示例
在渲染React组件前,先判断路由有效性,再设置响应状态码:
import React from 'react'; import { renderToString } from 'react-dom/server'; import { StaticRouter } from 'react-router-dom/server'; import App from './App'; import express from 'express'; const app = express(); function checkValidRoute(path) { // 自定义逻辑:校验路由是否存在 const validRoutes = ['/', '/about']; return validRoutes.includes(path); } app.get('*', (req, res) => { const statusCode = checkValidRoute(req.path) ? 200 : 404; const appHtml = renderToString( <StaticRouter location={req.path}> <App /> </StaticRouter> ); const html = ` <!DOCTYPE html> <html> <head><title>${statusCode === 404 ? '404页面' : '首页'}</title></head> <body>${appHtml}</body> </html> `; res.status(statusCode).send(html); }); app.listen(3000);
3. 在NotFound页面发送真实的404状态码
SSR/预渲染场景
直接在服务器端设置响应状态码为404即可,这是浏览器和搜索引擎能识别的真实HTTP状态码,无需额外客户端处理。
SPA场景(客户端内部跳转)
纯客户端场景下,浏览器的状态码由首次请求决定,无法直接修改。但可以通过以下方式补充:
- 向服务器发送404标记请求:在NotFound组件挂载时,发送HEAD请求到服务器端点,让服务器记录404访问:
import { useEffect } from 'react'; function NotFound() { useEffect(() => { // 发送HEAD请求,服务器返回404状态码 fetch('/api/mark-404', { method: 'HEAD' }); }, []); return <h1>404 - 页面不存在</h1>; }
服务器端对应端点:
app.head('/api/mark-404', (req, res) => { res.status(404).end(); });
- 添加搜索引擎识别标签:在NotFound页面加入
meta标签,告知搜索引擎这是404页面:
<meta name="robots" content="noindex, nofollow" />
内容的提问来源于stack exchange,提问作者Bardhavar Ravindhar
相关产品推荐
相关产品推荐

