将静态 HTML 网站转成 Jekyll 站点(更便于管理和改版)

10 February 2017 tomjoht tomjoht

如果你正在为你的 Jekyll 网站寻找主题模板,你不必将范围局限在一些现有的 Jekyll 主题。所有静态 HTML 模板都可以轻易转换成 Jekyll 主题。将静态 HTML 网站转成 Jekyll 站点也是一样的道理。

Jekyll 可以将网站的内容和模板分离,所以在你修改静态网站的界面或者功能时,只需修改主题模板文件即可(如页面通用部分、导航、列表、摘要、网站地图等),而不需要去修改一个个静态HTML文件。

你可以将任何 HTML 网站转成 Jekyll 主题模板,这将为你提供更多 Jekyll 主题模板选择,而不是在线搜索 Jekyll 主题模板,你可以选择任何 HTML 主题模板,快速 Jekyll-ize(Jekyll 化),并使用 Jekyll 构建生成 静态 HTML 网站。

虽然 Jekyll 网站可以实现一些复杂的功能和控件,本教程会着重讲核心基础的内容,便于你快速上手。

什么是 Jekyll 网站

我们将从最基础的知识开始,将 Jekyll 网站还原到最基本状态,便于你理解 Jekyll 是如何运作的。如果你还没有安装 Jekyll gem,请按照安装文档安装它。

一个最 基本的 Jekyll 站点 只需以下三个文件:

  • _config.yml 站点配置文件
  • _layouts/default.html 布局文件(主题模板)
  • index.md 首页文件(页面头部参数配置布局:layout: default
.
├── _config.yml
├── _layouts
│   └── default.html
└── index.md

创建一个名为 my_jekyll_site 的文件夹,创建这三个文件,并按照上面目录结构将 default.html 放到 _layouts 目录。

touch _config.yml index.md default.html
mkdir _layouts && mv default.html _layouts

用你喜欢的文本、代码编辑器打开 default.html 文件和 index.md 文件,并添加对应内容,具体如下所示:

_config.yml

name: 我的 Jekyll 网站

_layouts/default.html

<!DOCTYPE html>
<html>
  <body>
     {{ content }}
  </body>
</html>

index.md

---
title: 首页
layout: default
---

# {{ page.title }}

使用 [Markdown](https://learnxinyminutes.com/docs/markdown/) 撰写内容。
纯文本格式可以让你更专注 **内容**。

<!--
你可以在 Markdown 文件(.md 或者 .markdown)中使用 HTML 标签,例如这个注释标签,它不会受到 Markdown 解析器的影响。
但是,如果你创建的事 HTML 文件(*.html),却直接在 HTML 文件中使用 markdown 语法,因为不会被解析。
-->

使用 cd 命令进入 my_jekyll_site 目录,并使用 jekyll serve 运行 Jekyll 服务:

cd my_jekyll_site
jekyll serve

如果您有 Gemfile,将 bundle exec jekyll serve 命令替代 jekyll serve使用 Bundler

当你运行 Jekyll 服务时,会获得临时预览网站的 URL: http://127.0.0.1:4000/http://localhost:4000/ 是一样的)。默认情况 Jekyll 构建的静态站点文件会存放在 _site 目录。

这是基本功能级别的 Jekyll 站点,以下介绍了 Jekyll 的运作过程:

  • _config.yml 站点配置文件包含 Jekyll 构建网站时使用的设置。当配置为空时,将使用默认值构建 Jekyll 站点。例如,需要将 Markdown 转换为 HTML,如果没有指定特定的过滤器(fitter)会默认自动使用 kramdown Markdown filter
  • Jekyll 会查找带有 front matter tags (页面头部参数)的文件(如在 index.md 开头以两组虚线 --- 包含参数 ),并处理文件(填充站点变量、渲染任何 Liquid 以及将 Markdown 转换为 HTML)。
  • Jekyll 将所有页面和文章的内容推送到 front matter 指定的布局模板文件(default)中的 {{ content }} 变量中。
  • 处理后的文件生成为 .html 文件存入 _site 目录。

你可以查看解读排序 order了解 Jekyll 是如何处理排序的。

对 Jekyll 网站构建的工作原理有了基本了解,你几乎可以将任何 HTML 主题模板转换为 Jekyll 站点。下面的内容将引导你按步骤开始操作。

1. 给你的默认布局( layout)创建模板

找到你需要的 HTML 主题模板,将其转为 default 布局(layout)。如果要转换或者克隆现有网站,可以在浏览器右键查看源代码。

假如你需要克隆公司网站创建一个同品牌的文档网站,或者说你有一个 HTML 制作的网站,你想把它转成 Jekyll 网站。那你需要先拿到网站的 HTML 源代码。

在复制站点时,请检查许可,确保你有权复制或使用代码,切勿侵权。

复制源代码并粘贴到 default.html 文件(确保这个文件是存放在 _layouts 文件夹中)。default.html 作为 Jekyll 站点的默认布局模板,Jekyll 构建网站时,页面和文章都会默认使用这个布局文件就成为了页面和文章的默认布局模板,Jekyll 构建网站时每个页面和文章—都会使用这个模板进行布局。

需要注意,确保你找到 HTML 模板没有包含 PHP 代码或其他动态程序语言代码,或者将这些动态重新语言代码转换为 HTML 或 Liquid。Liquid 是Jekyll 的模板系统 ,用于获取动态内容。

在浏览器打开 default.html 文件,确保网站的界面布局、内容和功能都与原网站一致。如果出现异常,你可能需要调整 CSS、JS 和图像的路径,以使它们正常工作。

如果你所复制的网站上的路径是相对路径,那么你需要将相同的资源下载到 Jekyll 网站对应路径中,或使用绝对路径指向原网站的相同资源。

Jekyll 提供了一些过滤器,可以在路径前面预设站点 URL。例如,你可以像这样为 CSS 样式表添加前缀:

{{ "/assets/style.css" | relative_url }}

如果您的网站没有存放域的根目录而是在子目录(例如, http://mysite.com/blog/ )。relative_url 过滤器会将配置文件中的 baseurl 值(例如 blog )添加到输入的内容前面。 “relative_url”过滤器会将配置文件中的baseurl值(比如“blog”)添加到输入的前面。如果你的网站是在域名的子路径而不是根路径上托管的(例如“http://mysite.com/blog/”),这会很有用。

您也可以使用 absolute_url 过滤器。它会把 url baseurl 值附加到输入内容的前面:

{{ "/assets/style.css" | absolute_url }}

你可以在站点配置文件(_config.yml)中设定 urlbaseurl ,如下:

url: http://mysite.com
baseurl: /blog

输出的结果为: http://mysite.com/blog/assets/style.css

需注意,任何页面 url 都以正斜杆开头 (/),所以 url or baseurl 末尾不需要添加斜杆。

并非一定使用 absolute_url 过滤器,你也可以直接使用相对路径,只要确保可以正常的呈现网站内容和样式既可以。

在浏览器访问本地default.html 页面,如果显示正常(所有的图片、样式)请继续。你可以将这个布局模板用于所有页面和文章,也可以根据需要创建多个模板。

在下一步,你需要用 Liquid 的标签替换 HTML 中的内容,作为占位符,这些占位符将由 Jekyll 动态填充数据。

2. 指定页面的内容部分

default.html 中找到页面标题的位置,一般是内容开始的地方,一般会用 h1 或者 h2 HTML 标签。将标签中的内容替换为 {{ page.title }}

删除内容的内容部分(保留其他所有内容:导航菜单、侧边栏、页脚等),并在原内容部分添加 {{ content }}标签。

刷新浏览器中打开的 default.html,检查布局确保没有删错关键的 div 标签和其他元素导致页面错位或内容缺失。

目前页面的标题和内容被删除显示占位符标签。

3. 创建多个带有 front matter 的文件

在根目录中创建 index.mdabout.md 文件。

在你的 index.md 文件中添加 titlelayout 两个 front matter 参数,如下:

---
title: 首页
layout: default
---

这里是首页的内容...

about.md 页面中添加类似 front matter 参数进行测试。

如果你不给页面指定布局,Jekyll 会渲染为一个没有样式的基本 HTML 页面。

4. 添加配置文件

在你的 Jekyll 站点根目录(站点的文件夹)下添加 _config.yml 配置文件,你可以根据需要在 _config.yml 中设定 Markdown 过滤器。如果不配置会默认使用 kramdown,它使用的是 GitHub Flavored Markdown (GFM) 处理器。如果你没有配置,你的配置文件将以下配置作为默认配置

markdown: kramdown
kramdown:
  input: GFM

你可以在 Jekyll 文档中找到其他的 Markdown 选项,不过你可能并不需要它们。

5. 测试你的页面

运行 jekyll serve 并在 index.htmlabout.html 页面之前切换。这两个页面应该都是按 default.html 默认布局模板显示。

至此,你已经完成为页面定义一个通用布局和将内容提取到单独的文件中的操作。

你可以根据需要创建很多不同的布局,然后你只需要在页面指定对应特定的布局即可,如下:

---
title: 首页
layout: homepage
---

然后这个页面会使用 _layouts 目录中的 homepage.html 布局模板对页面进行渲染。

你可以在 _config.yml 配置文件中,对页面、文章或者 集合 collections 设置 默认的页面头部参数 default front matter tags,这样做你就无需每个页面或者每篇文章都重复去写页面头部参数 front matter。

6. 配置站点变量

前面已经使用 {{ page.title }} 填充了页面的标题,接着继续填充更多标题 title 标签。在页面中还有一个 title 标签,标签的内容会显示在浏览器窗口标题或者 tab 标签上,还有搜索引擎的搜索结果页。

在布局 default.html 中,查找 head 标签下的 title 标签:

<title>我的Jekyll网站</title>

将标签中的内容替换为页面标题变量和站点标题变量:

<title>{{ page.title }} | {{ site.title }}</title>

打开 _config.yml 找到 title 属性(如果没有该参数新增即可)并配置网站名称,值为你网站名称,如下:

title: 我的Jekyll网站

你在 _config.yml 配置文件中添加任何属性都可以通过 site 命名空间访问。而页面中的页面头部参数 front matter 的内容则都可以 page 命名空间访问。在 site 或者 page 与属性直接加个 . 来访问该值,如页面标题 page.title 或者 站点标题 site.title

在终端(cmd)界面按下Ctrl + C 停止 jekyll 服务,并重新输入 Jekyll 服务命令重新运行 Jekyll 验证 title(站点名称) 标签是否正确填充。

每次修改 _config.yml 配置文件后都需要重新启动 Jekyll 服务才能生效。而修改其他文件 Jekyll 会自动获取修改并重新构建。

如果你的站点中还需要添加其他变量,按上述步骤操作即可。

7. 在主页上展示文章

经常我们可以看到一个网站或者博客首页都会展示很多文章或者文章链接。为了让我们可以多展示一些内容,现在我们开始创建一些文章。

Jekyll 要求文章文件必须存放在 _posts 文件夹目录下面,并且文件的命名必须是 YYYY-MM-DD-title.md (年-月-日-标题)的格式,如果不满足这两个要求就会被视为页面处理,文章命名示例:

  • 2025-05-02-my-first-post.md
  • 2025-05-15-my-second-post.md
  • 2025-05-08-my-third-post.md

创建文章后,记得在文章中添加一些基本内容:

---
title: 我的第一篇文章
layout: default
---

这里是文章的内容..

现在我们创建一个显示文章的布局。在 _layouts 文件夹中创建一个名为 home.html 的新文件,并添加以代码:

---
layout: default
---

{{ content }}
<ul class="myposts">
{% for post in site.posts %}
    <li><a href="{{ post.url }}">{{ post.title}}</a>
    <span class="postDate">{{ post.date | date: "%b %-d, %Y" }}</span>
    </li>
{% endfor %}
</ul>

在根目录创建一个名为 blog.md 的文件,并指定 home 布局模板:

---
title: Blog
layout: home
---

这样配置,blog.md 的内容会被推送到 home 布局中的 {{ content }} 标签中。然后,home 布局会被推送到 default 布局中的 {{ content }} 标签中。

布局 layout 的工作原理

当一个布局文件指定另一个布局时,意味着该布局的内容会被嵌入到所指定布局的 {{ content }} 标签中。可以把布局想象成盒子里面装着一个盒子,一个层套一层,每个布局都可以随意嵌入到它所指定的另一个布局中(当然不能乱套用,否则页面会很乱)。

Jekyll 布局的工作方式如下图所示:

Concept of Jekyll layouts

在这个例子中, Markdown 文档 document.md 布局指定了 layout: docs ,它的内容被推送到布局文件 docs.html{{ content }} 标签中。由于 docs 布局本身指定了 layout: page,所以 docs.html 的内容被推送到布局文件 page.html{{ content }} 标签中。最后,由于 page 布局指定了 layout: default,所以 page.html 的内容被推送到布局文件 default.html{{ content }} 标签中。

以上是一个较为复杂的示例,或许你并不需要嵌套这么多布局。你可以根据你自己的需求设计布局文件的嵌套结构。一般我们会为页面指定一个布局 page,为文章指定一个布局post,然后可能还会为首页或者列表页指定一个布局,这些布局都可以继承 default 布局模板,或者这些页面可以直接就用 default 布局模板。

在浏览器中打开 blog.html,查看文章列表(本地运行 Jekyll 服务,该文件的完整预览地址可能是:http://127.0.0.1:4000/blog.html)。

需要注意,你不一定要把文章链接放到一个 blog.html 页面,这里只是为了便于理解举例,你可以使用简单的 for 循环语句将文章列表添加到任意页面,比如添加在 index.md,可以在首页查看文章列表。

但是不建议这些 for 循环语句放在页面中,而是放在布局 layout 中,便于后期管理维护。

布局至少应包含 {{ content }} 标签,渲染时呈现选择该布局的 内容

For 循环语句(For loops)

在这里,我们稍微停下来,仔细看看 for 循环的逻辑。Liquid 中的 for 循环 是最常用的 Liquid 标签之一。For 循环 允许你遍历 Jekyll 网站中的内容并构建出你想要的结果。for 循环还提供了一些基于当前循环位置的特殊属性,比如是否是第一次或最后一次迭代等。

我们目前只是简单地了解了 for 循环在获取文章时的基本用法。比如,如果你只想显示某个特定分类下的文章,可以在文章的 Front Matter(页面头部参数)中添加 categories 属性,然后在这些分类中查找文章。你还可以通过添加 limit 属性来限制结果数量。下面是一个示例:

<ul class="myposts">
{% for post in site.categories.podcasts limit:3 %}
    <li><a href="{{ post.url }}">{{ post.title}}</a>
    <span class="postDate">{{ post.date | date: "%b %-d, %Y" }}</span>
    </li>
{% endfor %}
</ul>

这个循环会获取分类为 podcasts 的最新三篇文章。 这个循环会获取最近的三篇在 Front Matter 中包含分类未 podcasts 的文章。


8. 配置网站导航菜单

在你配置完文章之后,我们来设置页面导航。大多数网站都会在侧边栏或页头区域有导航菜单。

在本教程中,我们假设你有一份简单的页面列表需要生成。如果你只有少量页面,可以使用 for 循环遍历 site.pages 对象,并按照每页的 Front Matter 属性进行排序。

先找到你代码中包含页面列表的部分。通常这是一组 <li> 子元素包含在一个 <ul> 元素中。将这段代码替换为以下内容:

<ul>
  {% assign mypages = site.pages | sort: "order" %}
    {% for page in mypages %}
    <li><a href="{{ page.url | absolute_url }}">{{ page.title }}</a></li>
    {% endfor %}
</ul>

这个例子假设每个页面都在其 Front Matter 中定义了 titleorder 属性,例如:

---
title: My page
order: 2
---

这里的 order 属性会决定页面的显示顺序,数字越小越靠前。

你也可以遍历一个单独的数据文件中维护的页面列表。如果你有很多页面,或者希望为页面存储其他属性,这种方法可能更合适。

要以这种方式管理页面链接,在你的 Jekyll 项目中创建一个名为 _data 的文件夹。在该文件夹中创建一个名为 navigation.yml 的文件,内容如下:

- title: Sample page 1
  url: /page-1-permalink/

- title: Sample page 2
  url: /page-2-permalink/

- title: Sample page 3
  url: /page-3-permalink/

如果你以前没写过 YAML,很快就能上手。你可以看看 YAML 能做些什么

你可以为每个项目存储任意其他属性,并按你希望的顺序排列这些列表项。

要从数据文件中打印页面列表,使用如下代码:

<ul>
    {% for link in site.data.navigation %}
    <li><a href="{{ link.url }}">{{ link.title }}</a></li>
    {% endfor %}
</ul>

如果你对导航有更复杂的需求,比如你在构建文档类网站时,可以查看我们提供的详细导航教程

9. 使用 Includes 简化网站结构

假设你的 default.html 布局文件非常庞大,编辑起来不方便。你可以通过将部分 HTML 代码提取到 include 文件中来简化布局。

首先,在项目根目录下创建一个名为 _includes 的文件夹。然后在该文件夹中创建一个名为 sidebar.html 的文件。

将原本在 default.html 中的侧边栏代码移入 sidebar.html 文件中。

然后,在 default.html 原本放置侧边栏代码的位置,使用如下方式引入该 include 文件:

{% include sidebar.html %}

你也可以以同样的方式拆分其他页面元素,例如页眉(header)或页脚(footer)。然后将这些通用元素复用于多个 layout 文件中,从而避免重复代码。


10. 添加 RSS 订阅功能

给你的 Jekyll 网站添加一个 RSS feed 是个不错的主意。这是 RSS 基本语法
在 Jekyll 中创建一个 RSS 文件很简单,只需要在项目根目录下创建一个名为 feed.xml 的文件,并加入以下内容:

---
layout: null
---

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">

    <channel>
        <title>{{ site.title }}</title>
        <link>{{ site.url }}</link>
        <atom:link href="{{ page.url | prepend: site.url }}" rel="self" type="application/rss+xml" />
        <description>{{ site.description }}</description>
        <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
        {% for post in site.posts %}
        <item>
            <title>{{ post.title }}</title>
            <link>
                {{ post.url | prepend: site.url }}
            </link>
            <description>
                {{ post.content | escape | truncate: '400' }}
            </description>
            <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
            <guid>
                {{ post.url | prepend: site.url }}
            </guid>
        </item>
        {% endfor %}
    </channel>
</rss>

确保你的 _config.yml 文件中包含 title(标题)、url(网址)和 description(描述)这几个属性。

这段代码使用了一个 for 循环来遍历你最近的 20 篇文章。文章内容会通过 Liquid 过滤器 进行转义,并截取为最后 400 个字符。

在你的 default.html 布局文件中,找到头部(header)里引用 RSS 或 Atom feed 的那一行,并将其替换为你刚刚创建的那个文件的引用。例如:

<link rel="alternate" type="application/rss+xml"  href="{{ site.url }}/feed.xml" title="{{ site.title }}">

你也可以通过添加一个名为 jekyll-feed 的 gem 来自动生成文章订阅 feed。这个 gem 同样适用于 GitHub Pages。

11. 添加 sitemap.xml 网站地图

最后,添加一个网站地图。在你的网站根目录下创建一个名为 sitemap.xml 的文件,并添加以下代码:

---
layout: null
search: exclude
---

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

    {% for page in site.pages %}
    <url>
        <loc>{{page.url}}</loc>
        <lastmod>{{site.time | date: '%Y-%m-%d' }}</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.5</priority>
    </url>
    {% endfor %}

    {% for post in site.posts %}
    <url>
        <loc>{{post.url}}</loc>
        <lastmod>{{site.time | date: '%Y-%m-%d' }}</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.5</priority>
    </url>
    {% endfor %}

</urlset>

我们再次使用了 for 循环来遍历所有的文章和页面,以便将它们添加到网站地图中。

你也可以通过添加一个名为 jekyll-sitemap 的 gem 来自动生成网站地图。这个 gem 同样适用于 GitHub Pages。

12. 添加外部服务

如果你还需要其他服务(比如联系表单、搜索、评论等等),可以寻找第三方服务。我们在资源页面上列出了一些集成方式,但在当今这个充满 SaaS 和 API 的时代,选择几乎是无限的。

你的 Jekyll 页面由 HTML、CSS 和 JavaScript 构成,所以几乎任何你需要嵌入的代码都可以正常工作。

在你集成这些服务的代码时,请注意:如果你 Jekyll 网站中的某个页面没有 Front Matter 标签(YAML 头信息),Jekyll 是不会处理该页面内容的。
这个页面在你构建网站时会被直接复制到 _site 文件夹中,不做任何处理。

如果你希望 Jekyll 处理某些页面内容(例如从配置文件中读取变量并填入页面),只需要给页面添加 Front Matter 标签。如果你不希望该页面使用任何布局模板,可以像下面这样设置 layout: null

---
layout: null
---

13. 结语

你现在拥有一个功能齐全的 Jekyll 站点,本教程中只介绍了基础知识,但 Jekyll 是可以实现一些复杂的功能。

如果你需要把你的网站发布到互联网,你可以考虑部署到 GitHub PagesNetlifyVercelRenderAmazon AWS S3 或者使用 s3_website plugin,当然你也可以生成 Jekyll 站点后将文件夹使用 FTP 工具上传到服务器。

Github Page、Gitlab Page、 Netify、Vercel、Render都有免费版本可以使用,你可以使用他们提供的免费二级域名或者目录搭建一个完全免费的 Jekyll 静态博客,当然你也可以使用自己的域名。

制作一个 Jekyll 主题,只需要将布局、内部文件和其他资源(layouts、includes、assets)打包到 Ruby gem 中。

其他资源

更多关于创建 Jekyll 站点的教程: