一次扑朔迷离的线上 404:MPA 应用集体失踪事件
2026-08-15
1505 字 | 8 分钟
统计加载中…… 阅读:    访客: 统计加载失败

实验室主页上,除了cyberchef,所有MPA应用(Mikutap、散点绘制、魔法阵工坊)一夜之间点进去全变成了项目的404页面。

而一天之前,这一切完全正常。 我确信自己没改掉什么重要的东西,只是觉得在主页新增一个直链这种小事,不可能造成这种影响。

症状很规整,规整到让人以为找到了规律:

  • 五个静态.html入口里,三个index.html全部404
  • 同时,SPA的正常路由也出现404
  • 只有cyberchef幸免

#

项目中一共有五个在静态资源中的页面。其中三个都显示了SPA 404页面。我猜,EdgeOne改了404路由行为

## 404
- [ ] https://lab.emumu.xyz/appx/mikutap/index.html
- [ ] https://lab.emumu.xyz/appx/scatter/index.html
- [ ] https://lab.emumu.xyz/appx/magicring/index.html
## 正常访问
- [x] https://lab.emumu.xyz/appx/cyberchef/CyberChef_v10.22.1.html
- [x] https://lab.emumu.xyz/appx/magicring/rulebook.html

需要注意的是,在这之前项目的404一直是EO默认404样式。我没去修的原因是在我发现这个问题不久后更新了对edgeone.json文件的支持,我想到可能还要去看文档,不如算了。

EO默认404页面
EO默认404页面

而我自己的404页面在我本地dev时总是合情合理地在它该出现的位置出现。

我的SPA 404页面。甚至还残留了css问题
我的SPA 404页面。甚至还残留了css问题

看起来就是平台把没命中静态文件的请求都回退到了SPA的index.html,客户端路由一看路径不认识,渲染了项目404页。合情合理,简直无懈可击。

而且更重要的是,现在我加载不动我收藏夹里的官网控制台,而其他网站一切正常。六六六,腾讯云跑路了。现在想来大概率是我改代理规则改坏了


#

症状很显然,其余三个全是index.html。我猜,文件名带index.html的被强制闪避了

于是我把三个MPA各复制出一份非index命名的入口文件,改配置、推送、部署。

新文件如下:

/appx/mikutap/index.html -> /appx/mikutap/mikutap.html
/appx/scatter/index.html -> /appx/scatter/scatter.html
/appx/magicring/index.html -> /appx/magicring/magicring.html
+ /appx/example/index.html

新文件scatter.html, magicring.html依然404。

新探针文件/appx/example/index.html可正常访问。这个新的example甚至就是我一天前删掉的。

无比诡异的实验结果正对着上一次的明显症状扇了一巴掌。

Deepseek思考良久,问我测试一下/appx/magicring/index.html?t=1

我靠,通了?我靠,我靠。难道真是缓存的问题?那这一致性不一致得有点严重了。

我本能地测了一下/appx/magicring/index.html

我靠,怎么也通了?


#

## 404
- [ ] https://lab.emumu.xyz/appx/mikutap/mikutap.html
- [ ] https://lab.emumu.xyz/appx/scatter/scatter.html
- [ ] https://lab.emumu.xyz/appx/magicring/magicring.html
## 正常访问
- [x] https://lab.emumu.xyz/appx/mikutap/index.html
- [x] https://lab.emumu.xyz/appx/scatter/index.html
- [x] https://lab.emumu.xyz/appx/magicring/rulebook.html
- [x] https://lab.emumu.xyz/appx/magicring/index.html
- [x] https://lab.emumu.xyz/appx/example/index.html
- [x] https://lab.emumu.xyz/appx/cyberchef/CyberChef_v10.22.1.html

debug到这里,目前以我的能力唯一能看出来的是,新传上去的东西没了,旧的活了。

简直扑朔迷离。

这时候D老师问我真是404吗?

D老师的harness是我正在测试的DSH,Deepseek推出的官方harness。各家的harness或多或少在shell上都有点问题出现,DSH亦是如此,D老师不止一次地向我强调HTTPS不可用,它最终使用HTTP直接访问是可以访问的。我仔细看它的工具调用想找出为什么,它访问页面判断404的方法是检查响应体长度。预渲染的长度是一样的。

等会,你检查响应体干什么,你不会看status_code吗?

我靠,这不是404,这tm不是200吗?

所有URL现在都是HTTP 200


#

首先,我的项目使用@preact/preset-vite+vite-prerender-plugin做SSR预渲染。这个插件的generateBundle干的事情是:

  1. //404开始渲染
  2. 每次渲染结果里的result.links递归入队继续预渲染
    • result.links来自preact-iso收集的所有<a href>链接
  3. 每个链接以emitFile写盘到dist的对应路径

其次,我的404页面有一个“猜你想去”。它检查你的路由,对比应用里所有的路由,计算编辑距离(具体来说是osa距离),然后列出其中最小的三条,摆成美味的anchor。

最后,我昨晚对主页进行了大改。引人注目的一项改动是添加了“新应用体验快链”,快链中有

<a href="/appx/magicring/index.html" target="_self" class="...">
<span class="...">新</span>
<span class="...">魔法阵工坊</span>
<span class="...">魔法阵编译器,一段代码生成一个魔法阵
</span>
<svg.../svg>
</a>

/appx/magicring/index.html就这样出现在了文档里。于是预渲染爬虫顺着它爬进了静态资源目录。

爬虫渲染这个路径时,SPA路由匹配不到,渲染出一个「起始404」页

而我的404页面实现了osa距离推荐,会把距离最近的前三条路径当建议链接列出来

这三条正好就是Mikutap、散点绘制、魔法阵工坊的index.html

爬虫又顺着这些建议链接继续爬,把三个入口全预渲染成了404页,emitFile写盘,覆盖了vite从public/拷过来的真实文件。

出于无向全连接图的某种性质,这三个页面的前三个相似路径还是这三个路径

于是,一个假的静态404页在dist/appx/mikutap/index.html生成了。


#

我唯一可预见的做错了的,是对SPA外的链接少写一个_blank

对,触发点就是首页快链缺blank。它是唯一能把爬虫带进/appx/的入口。/all中有所有应用的链接,但它们都不会把爬虫带进去,因为_blank是安全词。

在应用的prerender函数里把/appx/链接过滤掉,爬虫就永远不会触碰这些路径:

export async function prerender(_: unknown) {
const result = await ssr(<App />);
// 过滤掉 /appx/* 链接:vite-prerender-plugin 会沿着 result.links 递归预渲染并写盘,
// 若包含 MPA 静态页路径,预渲染出的 SPA 页面会覆盖 public/appx 下的真实文件。
const links = [...(result.links ?? [])].filter(
(url) => !url.startsWith("/appx/"),
);
// ...SEO 处理...
return { ...result, links, html };
}

本文由Deepseek参与写作,已由我本人审阅批改确保内容准确性。

一次扑朔迷离的线上 404:MPA 应用集体失踪事件
https://blog.emumu.xyz/posts/2026-08-15-00/
作者
月宮絵夢
发布于
2026-08-15
许可协议
CC BY-NC-SA 4.0
Loading...