当前位置: 首页 > 工具软件 > jekyll-toc > 使用案例 >

jekyll、hexo、hugo 互相迁移时关于永久链接的问题

南宫森
2023-12-01

说明

在各个静态博客网站生成工具之间迁移文章时,可能会遇到链接不一致的问题。

比如你在 jekyll 配置好了,文章链接是 https://hqweay.cn/2019/09/23/new-post 。迁移到 hexo ,文章链接就变成了 https://hqweay.cn/2019/09/23/2019-09-23-new-post

通常,为了 SEO、使用第三方评论、或其它原因,我们总希望博客迁移后,链接保持能不变。这里讨论一下我使用 jekyllhexohugo 在迁移数据时的一些感想。


先给一下方案,我建议文章按照 year-month-day-title.md ,即 年-月-日-标题.md 的格式命名。比如 2019-09-22-new-post.md 。之所以建议这样命名,是因为 jekyll 要求文章的文件名必须遵循这种格式。而 hexohugo 则没有这样的要求,后两者默认 文件名 作为标题。

以这种方式命名,hexohugo 仍可以通过配置获取到真正的 title 。而若不这样这样命名,如果想使用 jekyll 还得修改文件名。

虽然我觉得接触过 hexo 和 hugo 的人恐怕不会想着回到 jekyll 了吧…

而且通过年、月、日、标题的命名,在文件夹排列看起来比较清爽,同时还可以避免文件名冲突。


而生成的链接,我建议使用 /year/month/day/title ,比如 https://hqweay.cn/2019/09/23/new-post

如果只用 title 作为链接,比如 https://hqweay.cn/new-post ,若两篇文章 title 一样的话,就会冲突。用年、月、日、标题确定唯一的文章,就很难冲突啦。

这点和上面文件夹命名同理。

其实只是为了不冲突,https://hqweay.cn/2019-09-23-new-post 这样的链接也行。不过把时间区分出来观感好点…


给出方式。

如何配置

jekyll

文件名 :year-month-day-title.md

配置文件 _config.yml 添加

permalink : /:year/:month/:title

hexo

文件名 :year-month-day-title.md

配置文件 config.yml 添加

new_post_name: :year-:month-:day-:title.md
permalink: :year/:month/:day/:title/

hugo

文件名 :year-month-day-title.md

配置文件 config.toml

[frontmatter]
date  = [":filename", ":default"]

[permalinks]
post = "/:year/:month/:day/:slug/"

这里先提一下,post = "/:year/:month/:slug/" 这条配置规则指的是 hugocontent文件夹下的 post 文件夹下的文章都用这条规则来解析。

如果 content 文件夹下还有其它文件夹,则其它文件夹下的文章的链接解析不受此规则影响。

比如 content 下有 studylife 两个文件夹,则两者都需要配置上。

[frontmatter]
date  = [":filename", ":default"]

[permalinks]
study = "/:year/:month/:slug/"
life = "/:year/:month/:slug/"

为啥呢?

说明

先提一下,现在手上没有 jekyll 环境,也没看过源代码,以下都是我的猜测理解…

一般的静态网页生成工具都提供文件名与链接地址的映射。

比如文件名为 2019-09-23-new-post.md ,若生成静态页面且部署后,访问的链接可能是这样的。

https://hqweay.cn/2019-09-23-new-post

观察这个链接,会注意到文件名被直接解析为文章链接的后缀。


静态网页生成工具通常通过 permalink 这个属性来配置链接的生成规则。permalinkPermanent Link 的缩写,可译作 永久链接 ,简单来讲,也就是指一个 url 对应一篇文章。


jekyll 中,文章的命名格式是 2019-09-23-new-post.md ,即 year-month-day-title.md 。这种命名格式是 jekyll 的要求。


在默认情况下,若配置文件中不配置 permalink ,或者配置 permalink: date ,链接就被解析为 https://hqweay.cn/2019/09/23/new-post.html

—注意,上面这样配置,会跟上后缀 .html

若配置为 permalink : /:year/:month/:title ,链接则解析为 https://hqweay.cn/2019/09/23/new-post

没有 .html 后缀。

具体配置方式比较多,详见官方文档。

从 jekyll 迁移至 hexo

hexojekyll 的不同之处在于,hexo 可以取博文在 Front Matter 中定义的时间

写文章时常常有这样的内容。

---
layout: post
title: 快乐星猫
date: 2017-08-20
categories: life
toc: true
tags: [充数]
description:
---

我是一只猫,快乐的星猫~

--- 中间那一坨就是 Front Matter

jekyll 规定了文件名格式为 year-month-day-title.md ,就是为了从文件名取 date

hexo 默认文件名为 title ,它优先从 front matter 里取 date


hexo 的链接和配置文件中两条属性相关。

permalink: :year/:month/:day/:title/ 链接的格式

new_post_name: :title.md 解析标题方式

上面列出来的是默认配置。

在默认配置下,如果文件名为 2019-09-23-new-post.md ,解析出来的链接为 http://hqweay.cn/2019/09/23/2019-09-23-new-post/

不对劲吧。

这就是因为在 hexopermalink 里,默认的 :year:month 等使用的是 front matter 里的 date


我们分析下链接 http://hqweay.cn/2019/09/23/2019-09-23-new-post/

前面的 2019/09/23 对应的是 front matter 里的 date,后面的 2019-09-23-new-post 对应的则是文件名。


为啥?

上面提到了。jekyll 要求的文件名格式是 year-month-day-title.md ,就是为了把文件名中的 yearmonth 等取为 date 。但是 hexo 没这个要求,文件名格式就是 title.md 。即,默认文件名作为 title。然后,取 front matter 里的时间作为 date


那咋整呢?如果要把博文从 jekyll 迁移到 hexo ,这不是有冲突吗。

这就需要用到上面的第二条属性了。

new_post_name: :title.md 解析标题方式

new_post_name 可以配置解析文件名的方式。

默认 new_post_name: :title.md 就是把文件名作为 title。

修改为 new_post_name: :year-:month-:day-:title.md

这时候,hexo 就会把文件名中定义的时间当作 date 使用了。


回头看一下。文件名为 2019-09-23-new-post.md

配置

new_post_name: :year-:month-:day-:title.md

permalink: :year/:month/:day/:title/

此时,链接就为 http://hqweay.cn/2019/09/23/2019-09-23-new-post/ 了。

从 hexo 迁移至 hugo

hugohexo 类似,默认以文件名作为 title

即便我们没使用过 hugo ,也可以畅想一下,hugo 里有没有这样的配置?

一:配置解析链接的规则。

二:从文件名提取真正的 title

带着疑问查看文档。

permalinks

首先看到了 permalinks 的配置。

https://gohugo.io/content-management/urls/#permalinks

[permalinks]
posts = "/:year/:month/:title/"

Only the content under posts/ will have the new URL structure. For example, the file content/posts/sample-entry.md with date: 2017-02-27T19:20:00-05:00 in its front matter will render to public/2017/02/sample-entry/index.html at build time and therefore be reachable at https://example.com/2017/02/sample-entry/.

只有 /posts 下的文件才会匹配这条链接解析规则。如,文件 content/posts/sample-entry.md ,它在 front matter 里配置了 date: 2017-02-27T19:20:00-05:00 。这个文件在 build 时就会被渲染为网页放到 public/2017/02/sample-entry/index.html ,通过链接 https://example.com/2017/02/sample-entry/ 访问。

这样可以配置解析链接的规则,但同时也如文档所说,此时使用的 datefront matter 里定义的,而且 title 是文件名

瞧瞧 hugo 文件的 front matter

瞧瞧 front matter

---
title: "快乐星猫"
date: 2019-09-23T23:00:01+08:00
draft: true
---

注意!

默认生成的文章 date 使用的时间格式是 YYYY-MM-DD HH:MM:SS +0800

格式不作说明了。

没看文档,网上资料说时间格式必须这样。从 hexo 迁移到 hugo ,也需要注意这个,把时间修改一下。

但是我貌似没修改也渲染出来了…

不过我现在不打算折腾 hugo,这个疑问先留着吧…

frontmatter

那有没有解析文件名的配置呢?

这里~


https://gohugo.io/getting-started/configuration/

:filename

Fetches the date from the content file’s filename. For example, 2018-02-22-mypage.md will extract the date 2018-02-22. Also, if slug is not set, mypage will be used as the value for .Slug.

An example:

[frontmatter]
date  = [":filename", ":default"]

The above will try first to extract the value for .Date from the filename, then it will look in front matter parameters date, publishDate and lastly lastmod.


配置

[frontmatter]
date  = [":filename", ":default"]

你看,这里 date 对应一个数组,hugo 会去这个数组,按照顺序寻找 date

在这里,hugo 就优先从文件名中获取 date

比如有篇文章命名为 2018-02-22-mypage.md ,那么其中的 2018-02-22 就会被提取为 date

如果文件名没有时间,就从 :default 去寻找。(具体看文档…)


同时,若 slug 没有设置,则 mypage 会设置为 slug

这里的 slug 是个新概念。slug 可以在 front matter 配置。

slug

看说明,

slug:The token to appear in the tail of the URL

这啥玩意…

我的理解是:反正看样子这玩意是用来配置 url 的,url 在哪配置,在 permalink 嘛。那这应该是配置 permalink 的一个变量。

先不管吧,反正只要我们按照 year-month-day-title.md 这样来命名文件,slug 在这里显然指的就是 title。(虽然 slug 的定义应该比这大…)


回到 permalink 的配置。确实有个 :slug

:slug

the content’s slug (or title if no slug is provided in the front matter)

这里的 :slug 就是指 title。

看到这,我明白 slug 与 title 的区别了。

如果我们用标题作文件名,链接也只用标题。

比如 post.md

解析为

https://hqweay.cn/post

如果文件名冲突咋办?

这时就可以在 front matter 里设置 slug 来区分。

另一个问题,文件名怎么会冲突呢?

前面提到过,在保存博文文件的 content 文件夹下可以分文件夹保存博文,不同文件夹下就可能文件名冲突。

如果我们不设置 permalinkscontent 下若有两个文件夹 lifestudylife 下有一个 post.md 。其实 post.md 链接会渲染为 https://hqweay.cn/life/post

但若设置了 permalinks ,链接就不会像这样默认加上子文件夹 life 了…


好,配置 permalinks

[permalinks]
post = "/:year/:month/:day/:slug/"

ojbk。


总结一下

总结一下。

先配置

[frontmatter]
date  = [":filename", ":default"]

优先从文件名获取 date 。然后把 title 解析为 slug

再通过

[permalinks]
post = "/:year/:month/:day/:slug/"

配置链接解析规则。

此时的 :year:month/:day 就是从文件名获取的 date

:slug 是文件名解析出来的 title

 类似资料: