刚刚遇到的,还热乎着呢

TL;DR 锅是PJAX的,可以通过修改 _config.yml 修复。

LiveRe评论框是静态博客的福音,它允许博主在不对后端业务逻辑做出任何修改的情况下向文章底部引入评论框。当然,有得必有失,引入LiveRe评论框需要你加载外部的 JS,这对页面的安全性构成了挑战。好在我这个博客不要求登录所以不会有 cookie 什么的,顶死了它给我做个重定向(那我就立即弃用)或者是插点广告进来(已经插了,被我掐死了)。

荡开一笔:如何屏蔽LiveRe自带的韩文广告?

办法很简单,在页面最后加入一段 <script>,代码如下:

1
2
3
4
5
> setInterval(function () {
> var box = document.querySelector(".trc_rbox_container");
> if(box) box.outerHTML = "";
> }, 2000);
>

据说修改 outerHTML 对 IE <= 10 不管用,没关系我们可以修改 innerHTML

1
2
3
4
5
> setInterval(function () {
> var box = document.querySelector(".trc_rbox_container");
> if(box) box.innerHTML = "";
> }, 2000);
>

还不放心?我们甚至还有 CSS <style> 标签:

1
2
3
4
> .trc_rbox_container {
> display: none !important;
> }
>

重回正题。某日我发现LiveRe提示我有人在我的 /Friend-Link 友链页面评论了,但是点开LiveRe提供的连接却没有看到任何评论。我一度以为是LiveRe抽风了没加载出来,但是后来发现从主页点击“友链”按钮就可以看到,但是刷新一下就没了。

回想起之前调试DISQUS的血泪教训,我就重点关注了一下 document.titlelocation.pathname 这两个量的值,果然发现了问题:从首页点进来的时候,location.pathname"/Friend-Link",但是刷新一次之后就会变成 "/Friend-Link/"。所以LiveRe认为这是两个页面,在后者上没有加载前者的评论。

真不巧。

那么这个多出来的 / 是哪里来的呢?

(此处省略在后端 node_modules 中遨游 5 分钟)

(什么?你问我为什么找的这么快?啧,编辑器的文件夹全局搜索功能不就是拿来干这个的嘛(逃

发现了 node_modules/hexo-server/lib/middlewares 里有个 route.js,其中第 22 到 31 行如下:

1
2
3
4
5
6
7
8
9
10
// When the URL is `foo/index.html` but users access `foo`, redirect to `foo/`.
if (!data) {
if (extname) return next();

url = encodeURI(url);
res.statusCode = 302;
res.setHeader('Location', root + url + '/');
res.end('Redirecting');
return;
}

ok,于是显然问题就出在这了。

但是还有另外一个问题没有找到原因:为什么从首页点击“友链”文字进入就不会跳转呢?

(此处省略打log调试 3 分钟)

谜底:感谢PJAX这个妖精,用了PJAX换页确实快,但是带来无数的坑真的是意想不到的。PJAX判断/Friend-Link 和当前页面同域,于是往 /Friend-Link?_pjax=body 发了一个 XMLHTTPRequest 请求,收到了 302 重定向的状态码。接着它按照状态码的指示请求了 /Friend-Link/,得到了该页面的 HTML 源码,并将其写入了当前的 DOM。随后它通过 history.pushState() 修改了浏览器的 location.pathname 而不引起页面刷新,但是此时修改的链接(见下附 jquery.pjax.min.js 代码)仍然是由 <a> 元素的 href 属性决定的:

1
window.history.pushState(null, "", e.requestUrl)

于是尽管实际加载的页面是 /Friend-Link/,但是 location.pathname 仍然是 /Friend-Link。于是LiveRe就懵了,做出了超出预期的行为。

修复方法:

_config.yml 中,每个链接的最后都加上 / 就好了,这样既不用改库(上次抓 Bug 一路抓到 jQuery 里去真是累死我了,详见 ahonn/hexo-theme-even#241 中的 Outdated 的 Code Review),也不用改 LiveRe(这个大概会更累)。

举例(修复后,每个url结尾都加了 /):

1
2
3
4
5
6
7
8
9
# ===========================================
# Menu Settings
# ===========================================
menu:
Home: https://jiejiss.com
Archives: /archives/
Tags: /tags/
About: /Contribution-Status/
friend: /Friend-Link/

搞定。

来源:https://blog.jiejiss.com/