实验室主页上,除了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文件的支持,我想到可能还要去看文档,不如算了。

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

看起来就是平台把没命中静态文件的请求都回退到了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.htmldebug到这里,目前以我的能力唯一能看出来的是,新传上去的东西没了,旧的活了。
简直扑朔迷离。
这时候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干的事情是:
- 从
/和/404开始渲染 - 每次渲染结果里的
result.links递归入队继续预渲染result.links来自preact-iso收集的所有<a href>链接
- 每个链接以
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参与写作,已由我本人审阅批改确保内容准确性。
