Hexo Change Permanent Link Format With Backward Compatibility

Recently I would like to simplify permanent link for each post. From:

/2021/03/21/migrateopsmanager.en/

To:

/migrateopsmanager.en/

Shorter URL is more concise and readable, as the date string makes no sense to users. But what's the meaning of URL backward compatibility?

Change Permanent Link Format Issue

According to the official document, changing permalink format is pretty easy: just modify :year/:month/:day/:title/ to :title/ would be OK. However, the real problem is that all existing incoming links will be invalid after this modification. Then the ranking of our site will be affected which is unacceptable.

Unlike WordPress, it's hard to make a 301 redirect in Hexo. I worked out some possible solutions:

  • Add a canonical link tag to <head> for each post
  • Generated two permalinks, making the old one redirects to the new one by the first solution
  • Keep existing permalinks unchanged, use new format for new posts

To be safe, I choose the last one. So how to implement it?

New Post New Permalink Format Implementation

The algorithm is straightforward: if the post creation time is after new_format_date, post process the permalink and remove the useless date string. We will try to write a fitler to implement it: https://hexo.io/api/filter

Hexo passes data to filters in sequence and the filters then modify the data one after the other.

The first argument passed into each filter is data. The data passed into the next filter can be modified by returning a new value. If nothing is returned, the data remains unmodified.

After reading documentation, we found a filter called # post-permalink which is used to determine the permalink of posts:

hexo.extend.filter.register('post_permalink', function(data){  
 // ...  
});

The document doesn't explain the input parameter in detail. Actually, different filters have different input data structures. Maybe we need to read the source code. Specifically, for this filter, data is the permalink string like this: 2021/03/21/migrateopsmanager.en/ .

Let's create a scripts folder in the Hexo root folder and write a script refinepermalink.js:

var new_format_date = new Date('2021-05-01');

hexo.extend.filter.register('post_permalink', function(original_link){
    var pivot = original_link.slice(0, -1).lastIndexOf("/")
    var date_str = original_link.substring(0, pivot);
    var date = new Date(date_str);
    var title = original_link.substring(pivot + 1);

    var result = original_link;
    if (date > new_format_date)
    {
        result = title;
        console.log(' ', date, '### Change permalink:', original_link, '-->', result);
    }
    return result;
});

The above implementation is self-explained. Execute hexo g and then we are done:

$ hexo g
INFO  Start processing
  2021-06-14T16:00:00.000Z ### Change permalink: 2021/06/15/changepermalinkformat/ --> changepermalinkformat/
  2021-05-01T16:00:00.000Z ### Change permalink: 2021/05/02/sqlservercleanupqueries/ --> sqlservercleanupqueries/
  2021-05-01T16:00:00.000Z ### Change permalink: 2021/05/02/sqlservercleanupqueries.en/ --> sqlservercleanupqueries.en/
INFO  Files loaded in 1.99 s
...

References

# 玩转Hexo的Scripts

# Getting started with Hexo Plug-ins, and scripts

# Redirecting Old Permalinks on Statically Generated Blogs