404.html必须严格小写、置于根目录、无路径前缀,且服务器须返回真实404状态码;HTML需含语义化404文字、UTF-8无BOM编码、内联CSS、可访问结构,并禁用前端模拟。

404.html 文件必须严格小写、放根目录、不带任何路径前缀
GitHub Pages、Netlify、Vercel、Cloudflare Pages 这些平台只认 404.html 这个确切文件名,且必须位于 Git 仓库或构建输出的最顶层目录。写成 404.htm、error404.html、pages/404.html 或 404.HTML 都不会被接管。
常见踩坑点:
- Windows 记事本保存时可能悄悄加 BOM 头,导致部署后页面空白或状态码失效;建议用 VS Code 等编辑器并确认编码为 UTF-8 without BOM
- Jekyll 用户需在
404.html开头加---\npermalink: /404.html\npublished: false\n---,否则会被当作普通文章渲染 - macOS 本地测试不区分大小写,但 Linux 服务器会严格校验 —— 提交前用
git ls-files | grep 404确认文件名是纯小写
服务器必须返回真实 404 HTTP 状态码,不能靠前端“模拟”
浏览器地址栏显示 /xxx 但 Network 面板里 Status 是 200 OK?那根本不是 404 页面。搜索引擎会把它当正常页面收录,用户刷新也得不到重试提示。
验证方式只有两个:
立即学习“前端免费学习笔记(深入)”;
-
curl -I https://yoursite.com/nonexistent-path,第一行必须是HTTP/1.1 404 Not Found - Chrome DevTools → Network → 访问一个明显不存在的路径(如
/xyz-abc)→ 看该请求的 Response Headers 中Status字段
不同环境配置要点:
- 静态托管(GitHub Pages):自动支持,但仅限根目录
404.html;Netlify 需在_redirects写/* /404.html 404 - Nginx:在
server块中加error_page 404 /404.html;,并确保location = /404.html存在且未被try_files规则覆盖 - Express:必须显式调用
res.status(404).sendFile(path.join(__dirname, '404.html')),不能只res.sendFile() - SPA(React/Vue):路由 fallback 规则如
try_files $uri $uri/ /index.html会吞掉所有 404,必须排除/404.html路径
HTML 结构必须语义化,<h1></h1> 里得有 “404” 文字
<h1></h1> 不是装饰,是搜索引擎和屏幕阅读器识别错误页的唯一可靠信号。用 SVG、CSS 伪元素、JS 动态插入 “404”,视障用户听不到,爬虫读不到。
底线结构示例(无 JS、无外部依赖):
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>404 - 页面未找到</title>
<meta name="robots" content="noindex">
<style>
body { margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
main { text-align: center; max-width: 600px; padding: 0 20px; }
h1 { font-size: clamp(2.5rem, 5vw, 4rem); margin: 0 0 1rem; }
p { color: #666; line-height: 1.6; }
a { color: #007bff; text-decoration: none; font-weight: 500; }
</style>
</head>
<body>
<main role="main">
<h1>404 Not Found</h1>
<p>抱歉,您访问的页面不存在。</p>
<p><a href="/">← 返回首页</a></p>
</main>
</body>
</html>关键点:
-
<title></title>必须含 “404”,否则搜索结果点进来像进了首页 -
<main role="main"></main>包裹核心内容,让屏幕阅读器跳过导航直读错误信息 - CSS 必须内联,
<style></style>里控制在 1KB 以内;禁用<link rel="stylesheet"> - 所有文字与背景对比度 ≥ 4.5:1(可用 webaim.org/contrastchecker 验证)
带搜索框的 404 页面,别用 JS 拦截表单提交
所谓“站内搜索”,只是把用户输入转发给 /search?q=xxx,不是在 404 页面里查数据库。加 JS 拦截、fetch、history.pushState 反而会让跳转失败、SEO 不友好、JS 禁用时直接失灵。
正确做法:
- 用标准
<form method="GET" action="/search"></form>,input 必须带name="q"(或你后端约定的参数名) - 不要写
onsubmit="return false"或event.preventDefault()—— 这会让表单完全不可用 - 给 input 加
autofocus,回车默认触发表单提交;避免type="search"(Safari 多出 × 按钮,样式干扰大) - 搜索框位置放在错误说明下方、返回首页链接上方,视觉流是:错误 → 解决入口 → 备选路径
如果站点搜索页实际路径是 /blog/search,action 就得写完整,不能只写 search —— 这是最常被忽略的硬编码陷阱。
真正难的不是写 HTML,而是让服务器每次对不存在路径都精准返回这个文件 + 404 状态码。哪怕结构再规范,只要状态码不对,就等于没做。


















