辛宝Otto

Be a Happy Man

最近在学 Nuxt.js

用 Netlify Decap 给 SSG 添加 CMS 后台功能

发布于2023-11-02

更新于2023-11-02

归类blogs

Tagpostcms

https://decapcms.org/

Open source content management for your Git workflow Git 工作流里的内容管理工具

Use Decap CMS with any static site generator for a faster and more flexible web project 给你的 SSG 网站更容易维护

  • 受众是谁?
    • 前端程序员
    • vuepress hexo 类似的博客
    • 基于 git / markdown 工作流实现博客更新的朋友
  • 干啥的?
  • 怎么用?
  • 什么原理?

记得退出。

这是干啥的?

给 SSG 文档添加 CMS 功能,引入过程无侵入补充功能,不需要改造项目。

传统的流程是这样的:修改 md 文件 - 提交到 Github - 触发 CICD - 文档更新。

如果有这样的功能就好了:

  • 现成的后台,负责维护白名单账号实现鉴权,比如账号系统、白名单 Github 账号,实现只有作者、有权限的人才能改
  • 自动提交改动,有个页面解析渲染 md 文件,新增修改结束自动提交
  • 最好线上维护,不用打开代码编辑器
  • 不要影响我现有的流程,我随时可以通过代码编辑器掌控

让 SSG 网站像知乎、掘金一样随时修改,(CICD 后) 立刻生效。

这个 Decap 就做到了这样,背后是 Netlify 公司维护的。官网 https://decapcms.org/

怎么做到的?

  • 通过 Github App 实现获取登录
  • 维护名单
  • 制作 Github Workflow 实现创建和合并

我要怎么用?

根据文档上看,这里以 vuepress 为例,其他的也都一样,因为对现有的流程是不侵入的。

分成三个步骤

  • 引入 sdk,能够访问 /admin 页面
  • 在 netifly 后台启用功能
  • 项目初始化添加授权验证的代码

引入页面

在 public 目录 .vuepress/public 里添加

admin/
- index.html
- config.yml

其中 index.html 是固定内容,空白的

<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta name="robots" content="noindex" />
  <title>Content Manager</title>
</head>
<body>
  <!-- Include the script that builds the page and powers Decap CMS -->
  <script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>

观察页面,发现有引入了一个 js,这个 js 包含了所有的内容。又因为 public 是纳入到最终产物的,所以,这个时候 /admin 页面已经可以访问了,当然也可以叫任意路由。

接下来就是配置后台内容了,因为这个页面需要登录,比如我们使用 github 来登录,需要有一个编辑表单,方便修改文件。

修改配置

这里细分成两部操作,一个是维护 admin/config.yml 配置文件,一个是启动对应功能。

需要说明的是,接下来的鉴权部分使用 Netlify 提供好的服务,暂时不考虑纳入现有平台和自定义后台部分

backend:
  name: git-gateway # 使用现成的服务
  branch: master # 修改的内容提交到哪个分支,比如 main/dev

默认情况,所有的修改会直接提交,也可以通过 workflow 实现,实现有有批准提交的操作。

adds an interface for drafting,reviewing,and approving posts。

因此可以添加一个顶级配置

# 顶级配置,不要缩进
publish_mode: editorial_workflow

用户可能会上传图片、媒体等内容,这里需要设定上传的目录、生成 url 的前缀,比如对于 a.jpg 我们希望把图片放到 /public/img 文件夹下,生成的 url 前缀是 /img,这样完整的地址就是 /img/a.jpg 了,因为不同的工具,位置和前缀不同,所以这里允许自定义。

# These lines should *not* be indented
media_folder: "static/images/uploads" # Media files will be stored in the repo under static/images/uploads
public_folder: "/images/uploads" # The src attribute for uploaded media will begin with /images/uploads

接下来就是正式配置表单字段了,因为 md 一般有 frontmatter 和 body,字段还是比较多的。这里配置用的是 collections

举个例子,一个典型的 md 内容是

---
layout: blog
title: "Let's Party"
date: 1999-12-31 11:59:59 -0800
thumbnail: "/images/prince.jpg"
rating: 5
---
这是正文内容

对应的配置长这样,比较容易理解

collections:
  - name: "blog" # Used in routes, e.g., /admin/collections/blog
    label: "Blog" # Used in the UI
    folder: "_posts/blog" # The path to the folder where the documents are stored
    create: true # Allow users to create new documents in this collection
    slug: "{{slug}}" # title.md
    fields: # The fields for each document, usually in front matter
      - {label: "Layout", name: "layout", widget: "hidden", default: "blog"}
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Rating (scale of 1-5)", name: "rating", widget: "number"}
      - {label: "Body", name: "body", widget: "markdown"}

通过区分不同的 layout,设定不同的 collections 的子项。name/label/folder/create/slug 很清晰,fields 也很清晰。

filter 是过滤的,这个略过。

以上是配置,准备下一步

配置后台

Netlify 提供了一个名为 Identity 的内置身份验证服务。这需要在 Netlify 后台启用功能,结果如下。

图裂了...

可以设置谁可以登录和注册。显然这里需要选择,仅邀请。免费额度是可以 5 个人。

Pasted image 20230901173443

后面通过邮件进行邀请和设置密码。

这里我选择使用 github 登录,我试了,邮箱和 github 邮箱一样就行。实时的。

Pasted image 20230901173554

进行编辑和 review 的过程,在这里

Pasted image 20230901182236