起因

hexojs/hexo #1775 BUG非常明显,在使用hexo 3.1.1搭建一个位于子目录下的博客,然后会发现home以及categories的链接全都忽略了子目录的设定。

经过

收到反馈之后,我在我的测试环境中也复现了这个bug。一开始还怀疑是主题的问题,专门测试了next主题,结果发现也存在这样的问题,于是就排除了主题方面的bug。 首先我们可以初步判断这个url生成出现了问题,参考landscape主题中此处的代码:

<% for (var i in theme.menu){ %>
	<a class="main-nav-link" href="<%- url_for(theme.menu[i]) %>"><%= i %></a>
<% } %>

这里调用了一个url_for函数来生成超链接,代码如下(去除了与本BUG无关的部分):

function urlForHelper(path, options) {
  path = path || '/';

  if (path[0] === '#' || path.substring(0, 2) === '//') {
    return path;
  }

  var config = this.config;
  var root = config.root;
  var data = url.parse(path);

  // Exit if this is an external path
  if (data.protocol) {
    return path;
  }

  // Prepend root path
  path = root + path;

  return path.replace(/\/{2,}/g, '/');
}

直觉告诉我,这个问题很有可能就是这个函数写搓了。

然而我仔细研究了一下,发现url_for的逻辑并没有什么问题。而且根据我脑补的代码执行情况来看,应该生成一个正确的链接才对,但是config.root偏偏就丢了。 真的是非常奇怪,一时之间,我完全懵逼展开了,不明白到底发生了什么。

转折

后来我跟我的朋友聊天的时候提到这个bug,结果他告诉我,这个url_for写搓了,我点点头,应该就是这样。然后他说,一个判断都没有中,直接返回自身了,还贴了一张图。图中的代码大致如下:

function urlForHelper(path, options){
  /* jshint validthis: true */
  path = path || '/';

  var config = this.config;
  var root = config.root;
  var data = url.parse(path);

  // Exit if this is an external path
  if (data.protocol || path.substring(0, 2) === '//'){
    return path;
  }

  // Prepend root path
  if (path[0] !== '/'){
    return root + path;
  }

  return path;
}

看到图我立马懵逼了,连忙说,不对啊,你这个不是最新版本的代码。他被我这气场吓到,弱弱回复,我是刚安装的hexo…。 我顿时明白自己错在哪里了,npm源里面的稳定版还是3.1.1,但是我们github库中的代码已经是3.2beta了。使用最新的代码测试以后,发现这个bug已经不存在了。 也就是说,我花一个下午的时间,对着最新版的代码找一个已经被fix的bug…

总结

这一次的事情非常乌龙,事后想想觉得自己真的太傻逼了。 吃一堑长一智,以后做debug工作的时候一定要分清楚线上和线下的代码,首先就要明确出问题的是哪个版本,然后再开展相应的分析。 除此以外,还跟我不重视流程有关系。尽管我总是让人提供各种version信息,但是我却总是在分析问题的时候忽略这些信息,没有把这些关键的信息加入到自己的分析过程中。 总结起来就是,too young ,姿势水平还有待提高。

更新日志

  • 2016年02月26日 初次发布