文章

从 Typecho 迁移到 Jekyll

从 Typecho 迁移到 Jekyll

由于腾讯云买的服务器明年到期,如果想要有优惠必定需要迁移到其他厂商,但是如果想要其他厂商就又需要走一遍备案流程,十分麻烦。考虑到过去3年,这台服务器除了搭建博客外,也没有什么其他用途(主要是国内服务器很多操作都比较繁琐),于是决定明年降配置,但是会继续考虑腾讯云。

其实以上种种原因都只是做出这个决定的其中几个因素,最重要的原因是这两年来(从2023年9月开始),在找工作的压力下,我实在无心维护这个博客。但是考虑到这也算作是我的作品之一,还是不忍放弃,我还时常回顾很多当时走过的路、踩过的坑,于是决定将全站迁移为静态网站。

至于为什么用 Jekyll,因为我找到一个名为 Chirpy 的主题,它功能实现完整,基本上可以做到“开箱即用”,于是决定就用它了。

安装 Jekyll

Jekyll 是一个简单的静态网站生成器,它采用 Ruby 编程语言编写,可以将 markdown 文本根据不同模板自动转换为网页。考虑到这个站点需要部署到国内服务器上,我们还是在本地安装一下环境,手动编译后再上传上去。

以下是本次安装用到的环境:

  • Ubuntu 24.04.2 LTS
  • Linux pve-testenv 6.8.0-55-generic #57-Ubuntu SMP PREEMPT_DYNAMIC Wed Feb 12 23:42:21 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

我们参考官方教程,先安装需要的程序,使用 apt 安装即可,无需编译。

1
sudo apt-get install ruby-full build-essential zlib1g-dev

接下来我们验证一下环境,只要没报错应该就行。

1
2
3
4
5
ruby -v
gem -v
gcc -v
g++ -v
make -v

由于需要更改环境变量 ~/.bashrc,根据官方的建议,我们新建一个用户,这个用户无需 sudo 权限。

1
sudo adduser jekyll

创建完成后切换到这个用户。

1
2
su jekyll
cd ~/

然后把下面的各种配置贴进去。

1
2
3
4
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc
echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc
echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

再安装 Jekyll 和 Bundler,理论上就能用了。

1
gem install jekyll bundler

导出文章

既然是迁移,那么肯定要把文章给导出来。这里我没找到 Typecho 直接导出为 Jekyll 格式的插件,但是找到了可以导出为 Hugo 格式的插件,由于两者较为相近,稍微改改就能用。

1
2
cd /path/to/typecho/usr/plugins
git clone https://github.com/lizheming/typecho-export-hugo.git Export2Hugo

启用插件后,上方菜单栏-控制台-导出至Hugo,开始导出。但下载后无法解压,尝试修改 Action.php 里第 69-73 行,改为 tar 打包:

1
2
3
4
5
$filename = "hugo.".date('Y-m-d').".tar.gz";
$outputFile = $dir."/".$filename;
exec("cd $dir && tar -czf $outputFile content"); 

header("Content-Type:application/tar+gzip");

但仍然提示文件错误,最后在服务器临时文件目录下 /tmp/Export2Hugo 直接下载回了本地,可以正常解压。

不过这只是意味着所有文章成功导出了,但我们还需要修改一下插件以匹配 Jekyll 的格式要求。

由于我们需要文章的更新时间,这里需要在最开始的 select 中添加 modified,因此需要改一下 SQL 查询语句,找到 $sql=<<<TEXT,然后修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
select 
  u.screenName author, 
  url authorUrl, 
  title, 
  type, 
  text, 
  created, 
  modified, 
  c.status status, 
  password, 
  t2.category, 
  t1.tags, 
  slug 
from 
  {$prefix}contents c 
  left join (
    select 
      cid, 
      CONCAT(
        '"', 
        group_concat(m.name SEPARATOR '","'), 
        '"'
      ) tags 
    from 
      {$prefix}metas m, 
      {$prefix}relationships r 
    where 
      m.mid = r.mid 
      and m.type = 'tag' 
    group by 
      cid
  ) t1 on c.cid = t1.cid 
  left join (
    select 
      cid, 
      CONCAT(
        '"', 
        GROUP_CONCAT(m.name SEPARATOR '","'), 
        '"'
      ) category 
    from 
      {$prefix}metas m, 
      {$prefix}relationships r 
    where 
      m.mid = r.mid 
      and m.type = 'category' 
    group by 
      cid
  ) t2 on c.cid = t2.cid 
  left join (
    select 
      uid, 
      screenName, 
      url 
    from 
      {$prefix}users
  ) as u on c.authorId = u.uid 
where 
  c.type in ('post', 'page');

然后我们要修改一下 foreach 里面的内容,首先为发布日期添加时区:

1
$time = date('Y-m-d H:i:s O', $content["created"]);

然后新增更新日期变量:

1
$updated_time = date('Y-m-d H:i:s O', $content["modified"]);

接下来我们修改一下写入 markdown 文件的头内容,根据自己的需求修改就好:

1
2
3
4
5
6
7
8
9
---
title: "$title"
author: "Dan"
categories: [ $categories ]
tags: [ $tags ]
slug: "$slug"
date: "$time"
last_modified_at: "$updated_time"
---

由于原文件名不符合 Jekyll 规范,还需要修改一下导出的文件名格式:

1
2
#$filename = str_replace(array(" ","?","\\","/" ,":" ,"|", "*" ),'-',$title).".md";
$filename = date('Y-m-d', $content["created"]) . '-' . str_replace(array(" ","?","\\","/" ,":" ,"|", "*" ), '-', $slug) . ".md";

总之由于每个人的设置有所不同,可能需要尝试多次才能导出自己满意的一份。

导入文章

由于我正式因为看上了 Chirpy 主题才决定使用 Jekyll,因此这里用它做演示。

我们需要先下载一个主题的仓库,然后修改一下文件夹的名字:

1
2
git clone git@github.com:cotes2020/chirpy-starter.git
mv chirpy-starter chirpy

接下来先不导入任何文章,直接运行一下看能不能跑起来,这里开发者非常贴心了帮我们写了一个 shell 脚本,因此我们直接运行它就行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
jekyll@pve-testenv:~/blog/chirpy$ tools/run.sh

> bundle exec jekyll s -l -H 127.0.0.1

Configuration file: /home/jekyll/blog/chirpy/_config.yml
            Source: /home/jekyll/blog/chirpy
       Destination: /home/jekyll/blog/chirpy/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
                    done in 5.473 seconds.
 Auto-regeneration: enabled for '/home/jekyll/blog/chirpy'
LiveReload address: http://127.0.0.1:35729
    Server address: http://127.0.0.1:4000/
  Server running... press ctrl-c to stop.

如果没问题就可以关闭了,将所有导出的文件都放到 _posts 文件夹目录,修改一下 _config.yml 文件。这里因为每个人应该有所不同,因此只挑几个来讲。

为了保证迁移后的链接与原来的链接保持一致,我们找到 permalink 参数,将它配置为与你原来博客差不多的样子,这里可以参考官方文档查看可配置选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
defaults:
  - scope:
      path: "" # An empty string here means all files in the project
      type: posts
    values:
      layout: post
      comments: true # Enable comments in posts.
      toc: true # Display TOC column in posts.
      # DO NOT modify the following parameter unless you are confident enough
      # to update the code of all other post links in this project.
      permalink: /:categories/:slug.html
  - scope:
      path: _drafts
    values:
      comments: false
  - scope:
      path: ""
      type: tabs # see `site.collections`
    values:
      layout: page
      permalink: /:slug/

由于开启 PWA 功能后会导致网站不会立即刷新,我们这里直接关闭掉它:

1
2
3
4
5
6
7
8
9
pwa:
  enabled: false # The option for PWA feature (installable)
  cache:
    enabled: false # The option for PWA offline cache
    # Paths defined here will be excluded from the PWA cache.
    # Usually its value is the `baseurl` of another website that
    # shares the same domain name as the current website.
    deny_paths:
      # - "/example"  # URLs match `<SITE_URL>/example/*` will not be cached by the PWA

由于本站是要放到国内部署,使用任何国外的 CDN 都算是为了加速而背道而驰,因此我们需要自己托管静态资源,这里我们修改这一段配置:

1
2
3
4
5
6
7
# Self-hosted static assets, optional › https://github.com/cotes2020/chirpy-static-assets
assets:
  self_host:
    enabled: true
    # specify the Jekyll environment, empty means both
    # only works if `assets.self_host.enabled` is 'true'
    # env: # [development | production]

然后还需要下载所有静态资源:

1
2
git submodule init
git submodule update

最后我们再部署一下试试:

1
tools/run.sh

部署

如果看起来都没什么问题,我们需要以 production 模式运行一次,在 _site 得到编译好的文件:

1
tools/run.sh -p

最后把这个文件打个包,部署到国内服务器就可以了:

1
tar -cvf _site.tar _site/
本文由作者按照 CC BY 4.0 进行授权