增加404页面
2025-07-27 17:13:48 # deploy # issue # vercel # hexo

本地正常,线上异常

新增的album类型页面,支持多级结构。

本地正常,vercel部署后部分页面404。

本地正常 线上404

404的页面都是album叶节点,即这些album没有子album,展示的是若干photo。
在public查看albums的目录结构如下:

1
2
3
4
5
6
7
8
9
10
albums/
├── animal
│   ├── cat
│   │   └── 1.jpg
│   ├── cat.html
│   ├── dog
│   │   └── 1.jpg
│   ├── dog.html
│   └── index.html
└── index.html

albums、animal是album分支节点,访问他们可以不加index.html;dog和cat是album叶节点,访问他们要加.html。
比如,animal的合法访问路径有/albums/animal、/albums/animal/index.html。
dog的合法访问路径只能是/albums/animal/dog.html。

从以上截图可以看到,访问/albums/animal/dog时,本地正常,线上404。线上的情况其实是正常的,因为dog没有index.html。那为什么本地开发能以异常的方式正常显示呢?

本地开发的异常行为

本地开发采用hexo server的方式,开启了文件监听,文件改变时重新生成静态页面。其实现细节并不需了解很多,猜测它还做了其他有助于文件定位的事,导致本无法显示的/albums/animal/dog能被正确的定位到/albums/animal/dog.html。

要验证这种猜测,可以使用http-server。

安装http-server

pnpm i http-server -g

开启本地服务器

在博客根目录,执行http-server ./public。如果没有生成public需要先hexo g生成。

访问/albums/animal/dog,被重定向到/albums/animal/dog/
http-server-1

/albums/animal/dog/本应返回index.html,但因为dog没有index.html,http-server返回了我们看到的页面内容,类似 ls /albums/animal/dog/
http-server-2

所以上面的猜测(有助于文件定位)正确,hexo server做了超出类似Webpack HMR的功能。以下是ChatGPT回答:

hexo server 虽然也能本地预览,但它会自动编译、支持 Hexo 的动态路由映射,有时和线上真实静态服务器行为不一致(比如 404、目录跳转)。
http-server 只负责原样输出静态文件,和你把 public 上传到线上主机的效果一样,更适合调试静态站点的真实表现。

解决方案

修改路径

从分支album到叶album的跳转是通过path,在叶album的path后面添加.html即可。
solution1
这种方式可以解决部分问题,但无法解决用户修改url导致的404,所以还需下面的方法配合。

新增404页面

创建404.md

执行hexo new page 404

修改内容

打开source/404.md,设置以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
---
title: '页面不存在!'
date: 2025-07-27 16:53:29
type: "404"
comments: false
permalink: /404
---

对不起,您所访问的页面不存在或者已删除。

将在 <span id="timeout" style="font-weight: 700;" >5</span> 秒后返回首页, [点这里](/) 立即返回首页。


<script>
let countTime = 5;

function count() {
document.getElementById('timeout').textContent = countTime;
countTime -= 1;
if(countTime === 0){
location.href = '/';
}
setTimeout(() => {
count();
}, 1000);
}

count();
</script>

修改layout/post.ejs

打开themes/oranges/layout/post.ejs,在<% if (!page.type) { %>上面添加以下内容。

1
2
3
4
5
6
7
8
<!-- 404 页面 -->
<% if (page.type === "404") { %>
<div class="container post-details album-index">
<div class="markdown-body">
<%- page.content %>
</div>
</div>
<% } %>

查看效果

访问http://localhost:4000/404

PS: hexo server开启的本地服务,如果修改url访问不存在的路径(比如/a/b/c/d),是不会定位到404页面。使用http-server却可以将任意不存在路径定位到404页,因此推荐上线之前用http-server测试下。