回到文章列表

调试笔记

页面都打开了,为什么导航还在等 #home

先敲错域名,又怀疑 Fake-IP,最后才发现是页面自己用 history.pushState 换了地址。

当时的画面很别扭:curl200 OK,GitHub Pages 说构建成功,Chrome 连标题都读出来了,自动化导航却死活不肯结束,二十秒后照样报超时。

“导航超时”四个字很容易把人往网络上带。我也顺着这条路绕了一圈。

先承认一个低级错误

最开始我访问了一个和项目很像、但其实不对的域名,浏览器安全策略直接拦下。没什么技术含量,就是地址记错了。

所以第一条很丢人也很有用:先看仓库里的 CNAME 和部署配置,别相信手指记得。

换回 arcuid.dev 后,安全拦截没了,超时还在。很好,至少现在只剩真正的问题。

Fake-IP 长得太像嫌疑人

本机开着 FlClash 的 TUN 和 Fake-IP,DNS 查出来是 28.x.x.x。这个地址看着非常可疑,但它只是代理生成的映射,不是网站真实 IP。

继续往下查,证据开始和“代理坏了”这个猜测打架:

  • curl 能通过同一映射获得 200
  • GitHub Pages API 显示构建完成;
  • HTTPS 证书与强制跳转正常;
  • Chrome 标签页能读取正确标题。

既然同一条链路能拿到页面,就不能只凭一个陌生 IP 给代理判刑。

页面加载以后,自己换了地址

旧站启动时会读 URL Hash,然后不管当前是什么状态,都执行:

history.pushState(null, '', `#${pageId}`);

访问 / 后,旧站在加载过程中主动把地址变成了 /#home。自动化工具还在等原来的目标,页面却半路改口,最后就这样互相等了二十秒。

直接访问 /#home,立刻成功。到这里,网络终于可以下班了。

顺手又翻出一个后退 Bug

旧实现监听到 popstate 后,又调用了会执行 pushState 的切页函数。用户想后退,代码却顺手再塞一条历史记录。前进后退两个按钮就这样被搅成一团。

修法是把“把页面画出来”和“往历史里写记录”拆开:

function renderPage(pageId) {
  // 只更新界面,不改历史记录
}

function navigateTo(pageId) {
  history.pushState({ pageId }, '', `#${pageId}`);
  renderPage(pageId);
}

window.addEventListener('popstate', () => {
  renderPage(readPageFromLocation());
});

以后再碰到,我会这么查

  1. 确认权威域名;
  2. 检查 HTTP 和部署状态;
  3. 检查浏览器当前 URL、标题和 DOM;
  4. 对比“请求地址”和“页面最终地址”;
  5. 最后才考虑修改系统网络配置。

如果一开始就关 TUN、改 DNS,页面的 pushState 还是会照常执行,只是现场多了几项不知道有没有影响的改动。

这次最有用的不是猜中,而是忍住别一次改三样。听着很普通,真排错时却很容易忘。

看到这里了

要不要说两句

评论还没加载,往下滚到这里才会去请求。