Hexo Netlify CMS 静态博客管理与写作

引言

我们都知道,Hexo 是一个静态部署博客的框架,优点在于速度快,成本低(无需服务器),缺点在于繁琐,你每次更新文章都需要去改代码,再部署推送,修改配置也是如此,你不能像WordPress一样直接在后台修改配置并使它生效。

不过有很多教程可以让你无需繁琐的部署,只管推送代码,通过GitHub Actions,travis-ci,Vercel,Netlify 等都可以便捷的进行博客的部署,只管写代码然后推送就好,类似的教程有非常多,在此就不再重复介绍。那么,我们是否可以在此基础上,更加便捷的进行静态博客的写作和管理?答案是可以的。

我们可以通过将博客部署到 Netlify,并使用 Netlify cms 来做到这一点。

首先,我们来了解一下配置完之后可以做到哪些事情?

  • 在线新建,编辑,预览,删除博客文章
  • 支持文章草稿,工作流
  • 支持对博客图片的管理
  • 支持在线修改博客配置,例如对首页顶部图的修改,友链的修改

图片预览

在线演示

为了更加直观,原作者做了一个已经配置完毕的博客,你可以在线体验上述功能 👉点我查看

简单说明

下面我将会以 Hexo + NexT 主题做演示,并配置 Fluid 主题 的友链功能,达到在线编辑预览友链的目的,但此方法不仅仅只适用于 Fluid 主题 的友链功能,其他各类主题也可以通过此方法达到在线修改配置的目的,只要你配置完成,几乎可以修改所有配置项。包括但不限于以下类型的文件yml、yaml、toml、json、md、markdown、html具体请查看 👉Netlify cms 文档。

具体配置

Netlify cms 使用的前提条件是你必须将博客部署到 Netlify 上。因为网上有很多部署教程,这里不再重复。

可以部署到其他托管网站上,但需要自行修改

具体可以查看:

准备工作

在部署完成后,你需要开启 Identity

进入设置中:

Registration preferences 修改为 Invite only 此项为是否开启注册,默认是开启注册。修改为 Invite only 后表示仅受邀请的用户可以注册,当然此项你可以在自己注册完毕之后再行修改。

下滑找到 Git Gateway 并开启。

至此准备工作完成。

修改博客配置

在博客根目录中找到 _config.yml 并修改,这一步是跳过文件夹渲染,不然后面会出错:

1
skip_render: admin/*

在博客 source 文件夹中,创建 admin 文件夹,并新建两个文件 index.htmlconfig.yml

index.html 中添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!doctype html>
<html>

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="x-UA-Compatible" content="IE=Edge">
<meta name="apple-mobile-web-app-status-bar-style" content="white" />
<script type="text/javascript" src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
<title>Fl0w3r</title>
</head>

<body>
<script defer="true" src="https://cdn.jsdelivr.net/npm/netlify-cms@2/dist/netlify-cms.js"></script>
</body>

</html>

因为涉及到 Jsdelivr 加速,所以我选择把两个 js 源文件下载到 theme\next\source\js 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!doctype html>
<html>

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="x-UA-Compatible" content="IE=Edge">
<meta name="apple-mobile-web-app-status-bar-style" content="white" />
- <script type="text/javascript" src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
+ <script type="text/javascript" src="js/netlify-identity-widget.js"></script>
<title>Fl0w3r</title>
</head>

<body>
- <script defer="true" src="https://cdn.jsdelivr.net/npm/netlify-cms@2/dist/netlify-cms.js"></script>
+ <script defer="true" src="js/netlify-cms.js"></script>
</body>

</html>

config.yml 中添加以下折叠内容:

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
backend:
name: git-gateway # https://github.com/netlify/netlify-cms
branch: main # 要更新的分支(可选;默认为主分支)

# This line should *not* be indented
publish_mode: editorial_workflow

# This line should *not* be indented
media_folder: "source/images/uploads" # 媒体文件将存储在图片/上载下的Repo中。
public_folder: "/images/uploads" # 上传的媒体的src属性将以/images/uploads开头。

site_url: https://www.myql.xyz # 网站网址
display_url: https://www.myql.xyz # 显示网址

locale: "zh_Hans" # 语言环境 https://github.com/netlify/netlify-cms/tree/master/packages/netlify-cms-locales/src

collections: # https://www.netlifycms.org/docs/configuration-options/#collections
- name: "posts" # 在路由中使用,例如:/admin/collections/blog。
label: "Post" # 在用户界面中使用
folder: "source/_posts" # 存储文件的文件夹的路径。
create: true # 允许用户在这个集合中创建新的文件。
fields: # 每份文件的字段,通常是前面的内容。
- {
label: "顶部图",
name: "banner_img",
widget: "image",
required: false,
}
- {
label: "文章封面",
name: "index_img",
widget: "image",
required: false,
}
- { label: "文章排序", name: "sticky", widget: "number", required: false }
- { label: "标题", name: "title", widget: "string" }
- {
label: "发布日期",
name: "date",
widget: "datetime",
format: "YYYY-MM-DD HH:mm:ss",
dateFormat: "YYYY-MM-DD",
timeFormat: "HH:mm:ss",
required: false,
}
- {
label: "更新日期",
name: "updated",
widget: "datetime",
format: "YYYY-MM-DD HH:mm:ss",
dateFormat: "YYYY-MM-DD",
timeFormat: "HH:mm:ss",
required: false,
}
- { label: "标签", name: "tags", widget: "list", required: false }
- { label: "分类", name: "categories", widget: "list", required: false }
- { label: "关键词", name: "keywords", widget: "list", required: false }
- { label: "摘要", name: "excerpt", widget: "list", required: false }
- { label: "内容", name: "body", widget: "markdown", required: false }
- {
label: "永久链接",
name: "permalink",
widget: "string",
required: false,
}
- {
label: "评论",
name: "comments",
widget: "boolean",
default: true,
required: false,
}

- name: "pages"
label: "Pages"
files:
- file: "source/about/index.md"
name: "about"
label: "关于"
fields:
- { label: "标题", name: "title", widget: "string" }
- { label: "内容", name: "body", widget: "markdown", required: false }
- {
label: "评论",
name: "comments",
widget: "boolean",
default: true,
required: false,
}

# 如果你不是fluid主题,请删除以下配置,或者对文件路径及字段进行修改
# - name: "settings"
# label: "settings"
# files:
# - file: "source/_data/fluid_config.yml"
# name: "fluid"
# label: "fluid主题配置"
# editor:
# preview: true # 是否开启编辑预览
# fields:
# - label: "首页"
# name: "index"
# widget: "object"
# collapsed: true # 是否折叠显示
# fields:
# - label: "顶部图"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "文章页"
# name: "post"
# widget: "object"
# collapsed: true
# fields:
# - label: "顶部图(默认)"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "文章封面图(默认)"
# name: "default_index_img"
# widget: "image"
# - label: "归档页"
# name: "archive"
# widget: "object"
# collapsed: true
# fields:
# - label: "顶部图"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "分类页"
# name: "category"
# widget: "object"
# collapsed: true
# fields:
# - label: "顶部图"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "标签页"
# name: "tag"
# widget: "object"
# collapsed: true
# fields:
# - label: "顶部图"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "关于页"
# name: "about"
# widget: "object"
# collapsed: true
# fields:
# - label: "顶部图"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "友链页面"
# name: "links"
# widget: "object"
# collapsed: true
# fields:
# - label: "顶部图"
# name: "banner_img"
# widget: "image"
# - label: "高度"
# name: "banner_img_height"
# widget: "number"
# - label: "项目"
# name: "items"
# widget: "list"
# fields:
# - {
# label: "网站名称",
# name: "title",
# widget: "string",
# required: false,
# }
# - {
# label: "网址描述",
# name: "intro",
# widget: "string",
# required: false,
# }
# - {
# label: "网站地址",
# name: "link",
# widget: "string",
# required: false,
# }
# - {
# label: "网站图片",
# name: "avatar",
# widget: "image",
# required: false,
# }

请注意,这里我对 Fluid 主题进行了配置,例如 banner_imgindex_img 等项目,不能正常使用请删除。如果你不是 Fluid 主题,请根据实际情况对 source\admin\config.yml 配置进行修改。

参考文章