what's jekyll
jekyll是一个集成在GitHub Pages中的静态站点生成器,通过极其简单的语法和规则构建整个静态站点,作为一个想要免费使用GitHub Pages搭建博客的人来说,jekyll是不二之选。
why jekyll
- Github Pages 的内置集成,官方推荐使用jekyll作为GitHub Pages的静态站点生成器
- 不用使用繁杂的Github Actions即可自动触发GitHub Pages的CICD
- 对比其他生成器,轻量,学习成本非常低,是最有性价比的博客生成器
- 以markdown为内容载体
- 丰富的主题样式可供选择,极简配置主题,无需你手动写样式
- ruby的配置模式以及工程化对程序员友好
45分钟指南
5分钟下载/安装
- 安装ruby installer RubyInstaller
选择最新版带有DEVKIT的Ruby版本
- 安装完成后,在命令行输入
ridk, 你可以看到会有ruby install的样式icon显示,此时在命令行输入ridk install并且选择MSYS2 and MINGW development toolchain, 键入3,即下图
如果出现错误:无法初始化事务处理 (无法锁定数据库) 错误:无法锁定数据库:Permission denied 请使用管理员身份运行。
- 通过gem安装jekyll以及bundler
命令行输入
gem install jekyll bundler
3分钟项目搭建
2分钟初始化项目
- 运行
bundle init
此时会生成gem file, 里面会自带一行代码:
source "https://rubygems.org"
- 这个是指定包管理的依赖所配置的源,由于国外服务器访问速度受限的缘故,在没有科学上网工具的情况下,建议换镜像源:
source "https://mirrors.tuna.tsinghua.edu.cn/rubygems/"
- 此时我们需要在当前文件(Gemfile)中写入安装主要依赖
gem "jekyll"
这里的jekyll是项目本地依赖而不是之前gem install的全局依赖,如果项目中(Gemfile中)有这个依赖优先用项目依赖中的版本
- 此时命令行运行
bundle
将安装所有Gemfile中的依赖
1分钟运行空项目
- 创建根文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Home</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
- 打包初始化项目
命令行运行
jekyll build
此时jekyll会将当前根目录以及其所有子目录相关代码打包生成_site目录,这里面就是打包后的文件(由于咱们初始化项目看不出来打包痕迹,后面随着内容增加以后,里面的文件会被压缩)
此时目录结构如下
.
├── _site
│ └── index.html
├── Gemfile
├── Gemfile.lock
└── index.html
- 运行项目
命令行执行
jekyll serve --livereload --port 3456
这里livereload是热更新(即每次修改代码都会自动更新,建议加上)--port指定运行端口3456
访问`http://localhost:3456/ 即可生成初始化项目
30分钟jekyll实践指南
文件组成
由于jekyll是针对markdown格式的静态生成器,所以他能将所有以md/markdown结尾文件为markdown格式的页面视为html文件,可以将markdown文件当作页面处理。由于markdown文件简单易用行,我们可以将除了根文件index.html以及后续所说的layouts等相关配置型文件使用html以外,其余页面使用md格式简易处理。
Front Matter
其被叫做:前置信息,这个是用于写入一些类似于html中的meta数据,来标识整个文件的信息。在jekyll中,每一个yml/markdown/html文件都可以在文件开头以如下形式引入:
---
变量名:变量值
---
Layout
前端有个叫做layout的概念,称为布局,意思是页面的结构模板,我们通过引用/继承布局来快速实现页面结构,所以,现在我们在根目录创建_layouts文件夹,在里面创建一个default.html文件来表示我们的默认布局,内容如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{{ page.title }}</title>
</head>
<body>
{{ content }}
</body>
</html>
此时目录如下
.
├── _layouts
│ └── default.html
├── _site
│ ├── about.html
│ └── index.html
├── about.md
├── Gemfile
├── Gemfile.lock
└── index.html
这里面用双花括号括起来的是jekyll自带的系统变量,如:
-
page page变量表示整个页面的信息,page.title会获取页面Front Matter中的title
-
content content 变量表示整个页面的内容,比如处在markdown文件中的所有文本
使用layout
这里我们在根目录中创建一个关于的page,使用markdown形式:
---
layout: default
title: About
---
This is XXX. A software developer.
访问http://localhost:3456/about/ 此时我们会看到about页面渲染出来,并且页面tab标签的title也变为了About
includes
此时我们发现一个问题:我们很难知道整个项目有什么页面,即:没有导航栏支撑,页面全靠用户手动输入特别麻烦,所以,我们使用includes来把整个导航栏加入到layout中
includes被称作重用代码片段,通过将重复的内容抽取到 _includes 文件夹中,我们可以在多个页面中轻松插入这些内容,减少重复工作并使代码更加简洁和易于维护。
创建_includes文件夹及其在其添加navigation.html:
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
由于是代码片段,navigation.html不需要保留完整的html文件格式,只需要相应的标签片段即可
此时目录格式:
.
├── _includes
│ └── navigation.html
├── _layouts
│ └── default.html
├── _site
│ ├── about.html
│ └── index.html
├── about.md
├── Gemfile
├── Gemfile.lock
└── index.html
并且在default.htmllayout中增加include语法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{{ page.title }}</title>
</head>
<body>
{% include navigation.html %} {{ content }}
</body>
</html>
此处{% %} 是专为jekyll自带语法的标识符,include将引入_includes目录中的文件作为代码片段使用。
我们访问任意链接(home、about)即可发现页面首部增加了导航栏,点击仍以链接即可跳转
另外我们可以通过jekyll系统变量来设置样式,使导航栏的地址出现聚焦态, 这里修改navigation.html中的代码:
<nav>
<a href="/" {% if page.url == "/" %}style="color: red;"{% endif %}>
Home
</a>
<a href="/about.html" {% if page.url == "/about.html" %}style="color: red;"{% endif %}>
About
</a>
</nav>
其中jekyll的if条件判断的语法通过条件判断开始符{% if xxx %}以及结束符{% endif %} 来进行判断,另外如果需要多个if 判断可以在其中加入{% elsif xxx %} 以及{% else %} 如下:
<nav>
<a href="/"
{% if page.url == "/" %}
style="color: red;"
{% elsif page.url == "/home.html" %}
style="color: blue;"
{% else %}
style="color: black;"
{% endif %}>
Home
</a>
<a href="/about.html"
{% if page.url == "/about.html" %}
style="color: orange;"
{% elsif page.url == "/info.html" %}
style="color: green;"
{% endif %}>
About
</a>
</nav>
Data Files
但是我们仍然发现这种配置十分麻烦,需要不断给navigation添加各种各样链接, 我们可以通过数据存储文件(Data Files)的方式来配置文件,这种文件配置信息一般存放在_data文件夹下,这种配置信息一般存为yml格式文件,于是我们创建 _data/navigation.yml, 如下:
- name: Home
link: /
- name: About
link: /about.html
_data文件夹中的信息是由jekyll系统变量site.data访问,如上面的数组化结构即site.data.navigation, 此时我们修改原来的navigation文件,_includes/navigation.html:
<nav>
{% for item in site.data.navigation %}
<a href="{{ item.link }}" {% if page.url == item.link %}style="color: red;"{% endif %}>
{{ item.name }}
</a>
{% endfor %}
</nav>
这里我们使用了jekyll中的for in循环语法,大大简化后期导航栏数据量剧增的逻辑
Assets
此时我们发现样式编辑挺麻烦的,需要对某个链接的tag加入行内样式。但其实,jekyll自带预编译器sass支持,我们可以将所有样式/图片文件/js脚本这里文件放置于assets目录中,如下:
.
├── assets
│ ├── css
│ ├── images
│ └── js
...
jekyll 处理sass默认会找_sass对应的文件,我们创建_sass/main.scss:
.current {
color: green;
}
在assets/css/styles.scss 我们写入:
---
---
@import "main";
并将样式引入到default布局中去,_layouts/default.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{{ page.title }}</title>
<link rel="stylesheet" href="/assets/css/styles.css" />
</head>
<body>
{% include navigation.html %} {{ content }}
</body>
</html>
此时我们可以应用我们所写的样式到navigation中,navigation.html:
<nav>
{% for item in site.data.navigation %}
<a href="{{ item.link }}"{% if page.url == item.link %} class="current"{% endif %}>{{ item.name }}</a>
{% endfor %}
</nav>
页面的聚焦导航链接的样式即变成了绿色
Blogging
接下来就到我们的博客编写环节,jekyll默认在_posts存放所有博客路径,并且以日期-文件名.md的默认格式命名来解析博客内容
- 我们创造一个博客例子,
_posts/2025-01-05-init.md:
---
layout: default
author: Norman Chen
---
This is a test post.
- 增加一个文章的布局,
_layouts/post.html, 如下:
---
layout: default
---
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }} - {{ page.author }}</p>
{{ content }}
其中 | 类似于Linux里面的管道运算符,将左侧数据通过右侧方法加工处理。 date_to_string 是jekyll自带的日期转字符串的方法。
- 我们在根目录增加一个blog页面来渲染整个博客页面,
blog.md:
---
layout: default
title: Blog
---
<h1>Latest Posts</h1>
<ul>
{% for post in site.posts %}
<li>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
{{ post.excerpt }}
</li>
{% endfor %}
</ul>
其中jekyll通过site.posts获取_posts中所有文章内容生成一个数组结构,每一项包含:
1. url标识每个文章地址
2. title可以自动从文章名中获取
3. excerpt则截取markdown中第一段的内容
- 修改data files里面的blog页面配置:
- name: Home
link: /
- name: About
link: /about.html
- name: Blog
link: /blog.html
此时我们自己在多创建几个博客页面,就能在项目中的Blog页面中分别看到对应信息了。
Collections
以上是所有jekyll基础内容,不过从上述内容我们发现,类似于_layouts,_includes这些都是jekyll指定好了的系统级集合,如果我们需要自己的集合并在页面中使用则需要自己配置.
我们需要在项目根目录中创建一个项目配置文件,比如创建一个作者集合用于标识文章的不同作者:
collections:
authors:
改写了根目录的配置需要重启项目,CTRL+C打断项目进程再执行:
jekyll serve --livereload --port 3456
此时我们需要给这个类型加入作者的信息,比如,创建_authors/jill.md:
---
short_name: jill
name: Jill Smith
position: Chief Editor
---
Jill is an avid fruit grower based in the south of France.
以及_authors/ted.md:
---
short_name: ted
name: Ted Doe
position: Writer
---
Ted has been eating fruit since he was baby.
我们创建一个新的页面来显示全体作者,staff.md:
---
layout: default
title: Staff
---
<h1>Staff</h1>
<ul>
{% for author in site.authors %}
<li>
<h2><a href="{{ author.url }}">{{ author.name }}</a></h2>
<h2>{{ author.name }}</h2>
<h3>{{ author.position }}</h3>
<p>{{ author.content | markdownify }}</p>
</li>
{% endfor %}
</ul>
这里面使用了管道运算符markdown格式化来处理author的文本信息
从根目录配置的authors可以直接从site通过site.authors访问
修改导航配置数据,_data/navigation.yml:
- name: Home
link: /
- name: About
link: /about.html
- name: Blog
link: /blog.html
- name: Staff
link: /staff.html
但此时我们发现配置的staff页面没有我们刚刚设置的内容,这是由于在_config.yml配置的集合字段默认不会给页面中展示,所以我们需要修改配置打开它,_config.yml:
collections:
authors:
output: true
重启项目就会发现staff页面里面的数据正常显示了 此时点击author链接即可以跳转到对应的author详情页。
我们再给集合加上layout, _layouts/author.html:
---
layout: default
---
<h1>{{ page.name }}</h1>
<h2>{{ page.position }}</h2>
{{ content }}
每次这种手动添加layout方式很麻烦,更简洁的做法是在全局yml配置文件设置默认配置,如下:
collections:
authors:
output: true
defaults:
- scope:
path: ''
type: 'authors'
values:
layout: 'author'
- scope:
path: ''
type: 'posts'
values:
layout: 'post'
- scope:
path: ''
values:
layout: 'default'
重启以后不在需要在页面上配置layout布局 Front Matter了(所有原先在 Front Matter上吗配置的layout均可以移除)
2分钟GitHub Pages项目部署
项目部署非常简单,只需要两步
-
新建github.io项目仓库 以用户名.gitlab.io的名称创建GitHub仓库(这里由于我创建过所以无法新建仓库)
-
指定对应的文件夹并保存
当项目在当前所选分支(此为main分支)上并以当前子目录(从图中看出我是将整个项目放置于子目录的docs文件夹中,这个因个人想法而异,当你的git地址与项目重合后可以选择root作为当前分支子文件夹路径,如下图)
此时选择右侧上方Visit site 按钮即可进入到对应链接。
5分钟主题选择
配置博客最有成就感的就是主题配置了
这里使用minima这一主题进行配置:
- 修改原来的依赖安装
source "https://mirrors.tuna.tsinghua.edu.cn/rubygems/"
# Use github-pages gem which will provide the correct Jekyll version
gem "github-pages", "~> 228"
gem "minima", "~> 2.5.1"
gem "faraday-retry"
gem "kramdown-parser-gfm"
gem "webrick"
gem "wdm", ">= 0.1.0" if Gem.win_platform?
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12"
gem "jekyll-seo-tag", "~> 2.8"
end
这里一开始只需新增minima依赖但是其又依赖后面几项才能保证稳定运行,所以均加上
- 在
_config.yml中进行主题配置
domain: ~~~~替换成你的域名~~~~
url: ~~~~替换成你的链接~~~~
baseurl: ""
title: my blog
email: ~~~~替换成你的邮箱~~~~
description: >- # this means to ignore newlines until "baseurl:"
for blog posts
github_username: jekyll
# Theme settings
theme: minima
plugins:
- jekyll-feed
- jekyll-seo-tag
# Minima specific settings
minima:
date_format: '%b %-d, %Y'
social_links:
github: jekyll
# Build settings
sass:
sass_dir: _sass
- 在css中引入minima样式
---
---
/* Import styles */
@import "minima";
@import "main";
等项目部署完成(不到1分钟)即可访问带有主题的链接