Hexo 修改 permalink 后旧文章链接重定向方案

打算做一下文章的SEO, hexo默认的文章链接过长不太利于SEO收录, 所以修改了文章的链接方式

但是搜索引擎已经收录了一些文章路径, 如果直接修改会使得搜索引擎全部404, 可能会降低网站权重.

所以需要一个方式来将旧文章链接重定向到新文章链接.

旧的文章链接格式为

_config.yml
permalink: :year/:month/:day/:title/

新的文章链接格式为

_config.yml
permalink: posts/:year:month:day:hour:minute:second/

我的解决方案是在生成静态文件时, 仍然生成旧的文章, 但是html内重定向到新的文章, 通过hexo的插件做到, 代码如下:

old-url-redirects.js
/* global hexo */
'use strict';

function escapeHtml(s) {
  return String(s)
    .replace(/&/g, '&')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

function buildRedirectHtml(targetUrl, canonicalUrl) {
  const safeTarget = escapeHtml(targetUrl);
  const safeCanonical = escapeHtml(canonicalUrl || targetUrl);
  return [
    '<!doctype html>',
    '<html lang="zh-CN">',
    '<head>',
    '  <meta charset="utf-8">',
    '  <meta name="viewport" content="width=device-width,initial-scale=1">',
    `  <link rel="canonical" href="${safeCanonical}">`,
    '  <meta http-equiv="refresh" content="0; url=' + safeTarget + '">',
    `  <title>Redirecting...</title>`,
    '</head>',
    '<body>',
    `  <script>location.replace(${JSON.stringify(targetUrl)});</script>`,
    `  <p>If you are not redirected, <a href="${safeTarget}">click here</a>.</p>`,
    '</body>',
    '</html>'
  ].join('\n');
}

// Generate redirect pages for legacy permalinks:
//   /:year/:month/:day/:title/
// Redirect to current permalink (e.g. /posts/YYYYMMDDHHmmss/)
hexo.extend.generator.register('legacy_permalink_redirects', function(locals) {
  const root = (hexo.config.root || '/').replace(/\/?$/, '/');
  const posts = locals.posts || [];
  const routes = [];

  posts.forEach(post => {
    if (!post || !post.date || !post.permalink) return;

    const y = post.date.format('YYYY');
    const m = post.date.format('MM');
    const d = post.date.format('DD');
    const legacyTitle = post.slug || post.title || '';
    if (!legacyTitle) return;

    // Hexo route keys use decoded paths. The server will decode
    // the URL before matching, so we keep the legacy path unencoded.
    const legacyPath = `${y}/${m}/${d}/${legacyTitle}/index.html`;

    // post.permalink is absolute; for redirects we prefer site-root relative.
    const targetUrl = root.replace(/\/$/, '') + post.path.replace(/^\/?/, '/');
    const canonicalUrl = post.permalink;

    routes.push({
      path: legacyPath,
      data: buildRedirectHtml(targetUrl, canonicalUrl)
    });
  });

  return routes;
});

这样就会生成如下文件, 在访问旧文章时会重定向到新文章:

index.html
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="canonical" href="https://simonkimi.githubio.io/posts/20260317205553/">
  <meta http-equiv="refresh" content="0; url=/posts/20260317205553/">
  <title>Redirecting...</title>
</head>
<body>
  <script>location.replace("/posts/20260317205553/");</script>
  <p>If you are not redirected, <a href="/posts/20260317205553/">click here</a>.</p>
</body>
</html>

Hexo 修改 permalink 后旧文章链接重定向方案
https://simonkimi.githubio.io/posts/20260317125553/
作者
simonkimi
发布于
2026年3月17日
许可协议