Leader 让我做 CMS 帮助中心的技术选型,我撸了 VuePress 和 GitBook,然后选择...

2,604 阅读10分钟

前言

因为自己平时经常写博客,也有博客网站,所以 Leader 叫我做一个 CMS 的帮助中心的技术选型,CMS 的帮助中心的功能:是通过文章来教用户如何使用我们的项目。

所以笔者要做一个静态网站的技术选型,笔者把网上流行的 VuePressGitBook 两种方式都尝试了一下,并做了对比,这里写篇文章总结一下,顺便把自己的博客网站重作一便,哈哈。

优惠消息

笔者觉得每个开发者都应该拥有自己的网站和服务器,这可是很酷的事情,学习 Linux、跑跑脚本、建站、搭博客啥的都行。

1. VuePress

1.1 简介

VuePressVue 驱动的静态网站生成器。

简洁至上

Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。

Vue 驱动

享受 Vue + webpack 的开发体验,可以在 Markdown 中使用 Vue 组件,又可以使用 Vue 来开发自定义主题。

高性能

VuePress 会为每个页面预渲染生成静态的 HTML,同时,每个页面被加载的时候,将作为 SPA 运行。

1.2 效果

首页:

评论:

效果详情请看:biaochenxuying.github.io/blog/

1.3 简单使用

像数 1, 2, 3 一样容易

# 安装
yarn global add vuepress # 或者:npm install -g vuepress

# 创建项目目录
mkdir vuepress-starter && cd vuepress-starter

# 新建一个 markdown 文件
echo '# Hello VuePress!' > README.md

# 开始写作
vuepress dev .

# 构建静态文件
vuepress build .

1.4 目录结构

VuePress 遵循 “约定优于配置” 的原则,推荐的目录结构如下:

├── docs
│   ├── .vuepress (可选的)
│   │   ├── components (可选的)
│   │   ├── theme (可选的)
│   │   │   └── Layout.vue
│   │   ├── public (可选的)
│   │   ├── styles (可选的)
│   │   │   ├── index.styl
│   │   │   └── palette.styl
│   │   ├── templates (可选的, 谨慎配置)
│   │   │   ├── dev.html
│   │   │   └── ssr.html
│   │   ├── config.js (可选的)
│   │   └── enhanceApp.js (可选的)
│   │ 
│   ├── README.md
│   ├── guide
│   │   └── README.md
│   └── config.md
│ 
└── package.json

注意:请留意目录名的大写。

  • docs/.vuepress: 用于存放全局的配置、组件、静态资源等。
  • docs/.vuepress/components: 该目录中的 Vue 组件将会被自动注册为全局组件。
  • docs/.vuepress/theme: 用于存放本地主题。
  • docs/.vuepress/styles: 用于存放样式相关的文件。
  • docs/.vuepress/styles/index.styl: 将会被自动应用的全局样式文件,会生成在最终的 CSS 文件结尾,具有比默认样式更高的优先级。
  • docs/.vuepress/styles/palette.styl: 用于重写默认颜色常量,或者设置新的 stylus 颜色常量。
  • docs/.vuepress/public: 静态资源目录。
  • docs/.vuepress/templates: 存储 HTML 模板文件。
  • docs/.vuepress/templates/dev.html: 用于开发环境的 HTML 模板文件。
  • docs/.vuepress/templates/ssr.html: 构建时基于 Vue SSRHTML 模板文件。
  • docs/.vuepress/config.js: 配置文件的入口文件,也可以是 YMLtoml
  • docs/.vuepress/enhanceApp.js: 客户端应用的增强。

注意

  1. 当你想要去自定义 templates/ssr.html 或 templates/dev.html 时,最好基于 默认的模板文件 来修改,否则可能会导致构建出错。

  2. 还有就是笔者的  templates/ssr.html 和 templates/dev.html 是有添加如下这一行代码的:

<meta id="referrer" name="referrer" content="never" />

因为笔者的图片都是存在简书上的,所以为了可以访问第三方图床的图片,才添加了这句代码,如果你的图片是存在本地的,去掉这句代码即可,至于具体原因请看笔者写的文章:前端解决第三方图片防盗链的办法 - html referrer 访问图片资源403问题

  1. 笔者的目录也是按官方推荐的来的,如下:

1.5 评论

评论功能用了 GitTalk。

1.5.1 申请一个 OAuth App

具体实践如下:

  1. 首先登录你的 GitHub 账号,然后点击进入Settings。

  1. 点击 OAuth Apps , Register a new application 或者 New OAuth App 。

  1. 输入信息。

image.png

  1. 应用信息说明:Client ID && Client Secret

创建成功有 Client IDClient Secret ,保存下来,后面我们会用到。

  1. 创建评论组件

Vuepress 默认 .vuepress / components 文件夹下的组件会全局注册,因此我们创建一个 comment 组件。

gittalk.css 请点击 这里

<template>
  <div class="gitalk-container">
    <div id="gitalk-container"></div>
  </div>
</template>
<script>
export default {
  name: 'comment',
  data() {
    return {};
  },
  mounted() {
    let body = document.querySelector('.gitalk-container');
    let script = document.createElement('script');
    script.src = 'https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js';
    body.appendChild(script);
    script.onload = () => {
      const commentConfig = {
        clientID: '你的clientID',
        clientSecret: '你的clientSecret',
        repo: '你的仓库名称',
        owner: '你的用户名',
        // 这里接受一个数组,可以添加多个管理员,可以是你自己
        admin: ['管理用户名'],
        // id 用于当前页面的唯一标识,一般来讲 pathname 足够了,
        // 但是如果你的 pathname 超过 50 个字符,GitHub 将不会成功创建 issue,此情况可以考虑给每个页面生成 hash 值的方法.
        id: location.pathname,
        distractionFreeMode: false,
      };
      const gitalk = new Gitalk(commentConfig);
      gitalk.render('gitalk-container');
    };
  },
};
</script>
<style>
@import '../css/gittalk.css';
</style>
  1. 使用评论组件

理论上,我们在每个 markdown 文件里直接加入这个组件即可,但是每次都添加有点麻烦,还是让 node 来帮我们吧

根目录创建 build 文件夹, 创建三个文件 addComponents.js, delComponents.js, findMarkdown.js, 分别代码如下:

// addComponents.js
const fs = require("fs");
const findMarkdown = require("./findMarkdown");
const rootDir = "./docs";

findMarkdown(rootDir, writeComponents);

function writeComponents(dir) {
    if (!/README/.test(dir)) {
        fs.appendFile(dir, `\n \n <comment/> \n `, err => {
            if (err) throw err;
            console.log(`add components to ${dir}`);
        });
    }
}
// delComponents.js
const fs = require("fs");
const findMarkdown = require("./findMarkdown");
const rootDir = "./docs";

findMarkdown(rootDir, delComponents);

function delComponents(dir) {
    fs.readFile(dir, "utf-8", (err, content) => {
        if (err) throw err;

        fs.writeFile(
            dir,
            content.replace(/\n \n <comment\/> \n /g, ""),
            err => {
                if (err) throw err;
                console.log(`del components from ${dir}`);
            }
        );
    });
}
// findMarkdown.js
const fs = require("fs");

function findMarkdown(dir, callback) {
    fs.readdir(dir, function(err, files) {
        if (err) throw err;
        files.forEach(fileName => {
            let innerDir = `${dir}/${fileName}`;
            if (fileName.indexOf(".") !== 0) {
                fs.stat(innerDir, function(err, stat) {
                    if (stat.isDirectory()) {
                        findMarkdown(innerDir, callback);
                    } else {
                        // 跳过readme 文件,当然你也可以自行修改
                        if (/\.md$/.test(fileName) && !/README/.test(fileName))
                            callback(innerDir);
                    }
                });
            }
        });
    });
}
module.exports = findMarkdown;

修改 package.jsonscripts, 先为每个 md 文件添加组件,然后打包,最后再一一删除 markdown 中的 comment 组件。

"build": "node ./builds/addComponents.js && vuepress build docs && node ./builds/delComponents.js",

笔者的项目里面是把添加了二条命令的,比如 npm run dev:mdnpm run build:md 才是有评论组件的。

"scripts": {
    "dev": "vuepress dev docs",
    "dev:md": "node ./builds/addComponents.js && vuepress dev docs && node ./builds/delComponents.js",
    "docs:dev": "vuepress dev docs",
    "build": "vuepress build docs",
    "build:md": "node ./builds/addComponents.js && vuepress build docs && node ./builds/delComponents.js",
    "docs:build": "vuepress build docs",
    "delay": "bash delay.sh",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

想要怎样的打包命令,自己修改就行。

  1. 注意:如果你的文章的评论要和 githubissues 的同步的话,还要在 issueslabel 里添加相应的 pathnamegitalk,其中 pathname 就是评论组件里面的 location.pathname

比如我的:

1.6 部署到 Github pages

当我们将文档写好后就到了我们最关心的地方了,怎么将打包后的代码推送到远程仓库的 gh-pages 分支上。

  1. 创建一个deploy.sh
touch deploy.sh
  1. 编写脚本
#!/usr/bin/env sh

# 确保脚本抛出遇到的错误
set -e

# 生成静态文件
npm run docs:build

# 进入生成的文件夹
cd docs/.vuepress/dist

# 如果是发布到自定义域名
# echo 'www.example.com' > CNAME

git init
git add -A
git commit -m 'deploy'

# 如果发布到 https://<USERNAME>.github.io
# git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git master

# 如果发布到 https://<USERNAME>.github.io/<REPO>
# git push -f git@github.com:<USERNAME>/<REPO>.git master:gh-pages

cd -

  1. 设置 package.json
{
    "scripts": {
        "deploy": "bash deploy.sh"
      },
}
  1. 发布
npm run deploy   // 即可自动构建部署到 github 上。
  1. 访问自己的域名,比如笔者的:biaochenxuying.github.io/blog/

详情移步 vuepress 官网 vuepress.vuejs.org

2. GitBook

效果:

效果详情请看:biaochenxuying.cn:2021

2.1 GitBook 常用指令

  • 安装 GitBooknpm i gitbook-cli -g
  • 初始化 GitBook 项目gitbook init
  • 安装 GitBook 依赖gitbook install
  • 开启 GitBook 服务gitbook serve
  • 打包 GitBook 项目gitbook build
  • GitBook 命令行查看gitbook -help
  • GitBook 版本查看gitbook -V

2.2 简单上手

然后,我们找个空文件夹,初始化一个 GitBook 项目。

  • gitbook init 初始化 README.md 和 SUMMARY.md 两个文件.
  • gitbook build 本地构建但不运行服务,默认输出到 _book/ 目录.
  • gitbook serve 本地构建并运行服务,默认访问 http://localhost:4000 实时预览.
- GitBook
 - README.md
 - SUMMARY.md

  • README.md 是默认首页文件,相当于网站的首页 index.html ,一般是介绍文字或相关导航链接.
  • SUMMARY.md 是默认概括文件,主要是根据该文件内容生成相应的目录结构,同 README.md 一样都是被 gitbook init 初始化默认创建的重要文件.
  • _book 是默认的输出目录,存放着原始 markdown 渲染完毕后的 html 文件,可以直接打包到服务器充当静态网站使用。一般是执行 gitbook buildgitbook serve 自动生成的.
  • book.json 是配置文件,用于个性化调整 gitbook 的相关配置,如定义电子书的标题、封面、作者等信息。虽然是手动创建但一般是必选的.
  • GLOSSARY.md 是默认的词汇表,主要说明专业词汇的详细解释,这样阅读到专业词汇时就会有相应提示信息,也是手动创建但是可选的.
  • LANGS.md 是默认的语言文件,用于国际化版本翻译和 GLOSSARY.md 一样是手动创建但是可选的.

book.json 的意思:

  1. title:网站标题
  2. author:网站作者
  3. description:网站功能描述
  4. language:网站使用语言
  5. styles:网站额外配置的样式表
  6. plugins:网站使用的插件
  7. pluginsConfig:网站使用的插件的额外配

笔者的 book.json:

{
  "title": "夜尽天明的博客",
  "author": "biaochenxuying",
  "description": "大前端技术为主,读书笔记、随笔、理财为辅,做个终身学习者。",
  "language": "zh-hans",
  "plugins": [
    "-highlight",
    "copy-code-button",
    "search-pro",
    "-search",
    "-lunr",
    "expandable-chapters",
    "splitter",
    "-sharing",
    "github-buttons",
    "donate",
    "tbfed-pagefooter",
    "baidu-tongji",
    "anchor-navigation-ex"
  ],
  "pluginsConfig": {
    "github-buttons": {
      "buttons": [
        {
          "user": "biaochenxuying",
          "repo": "blog", 
          "type": "star",
          "count": true,
          "size": "small"
        }, 
        {
          "user": "biaochenxuying",
          "width": "160", 
          "type": "follow", 
          "count": true,
          "size": "small"
        }
      ]
    },
    "donate": {
      "button": "打赏",
      "wechatText": "微信打赏",
      "wechat": "https://camo.githubusercontent.com/ee094d402f957e5d656a399b9dc50ff8c010114e/68747470733a2f2f75706c6f61642d696d616765732e6a69616e7368752e696f2f75706c6f61645f696d616765732f31323839303831392d666661623762643234643038633030642e6a7065673f696d6167654d6f6772322f6175746f2d6f7269656e742f7374726970253743696d61676556696577322f322f772f31323430"
    },
    "tbfed-pagefooter": {
      "copyright":"Copyright &copy biaochenxuying.cn 2019",
      "modify_label": "该文件修订时间:",
      "modify_format": "YYYY-MM-DD HH:mm:ss"
    },
    "baidu-tongji": {
      "token": "XXXXX"
    },
    "anchor-navigation-ex": {
      "showLevel": false
    }
  }
}

2.3 插件

插件的配置可以说是 GitBook 的核心。

详情可以看 GitBook - 快速打造可留言的博客,这里就不展开讲了。

3. VuePress VS GitBook

相同点

  1. 目前只支持 markdown 格式,图片、视频 等静态资源可以保存在本地,或者保存到允许访问的第三方服务商(如七牛云);
  2. 如果是 world 文档或者 html 格式,要转换成 md 格式才行。
  3. 找了几个 world 文档转换成 md 格式的工具,都不好用,特别是有原文档有图片的时候。

不同点

  1. GitBook 的配置成本很小,可以本地编辑,然后直接部署;GitBook 官方还有个在线编辑器,不过内容要存在 GitBook 的服务器上。
  2. VuePress 的配置成本稍稍大一点,不过可以使用 Vue 的语法与组件,定制化更自由一点,而且 VuePress 中编写 Vue 和平时一样,学习成本几乎为零,可以本地用 VsCode 编辑,然后直接命令行部署。

结论

  1. 都要用 markdown 语法来写文章,markdown 也就几个常用语法而已,非常简单上手。
  2. 非技术人员推荐用 GitBook,技术人员推荐用 VuePress,特别是前端技术人员
  3. 个人更喜欢 VuePress

4. 项目源码

本文中使用 VuePressGitBook 的搭建的完整示例代码都已经上传到 GitHub 上了,可以自行下载来用。

只要把其中的一些配置信息换成自己的就行,比如 仓库Client ID && Client Secret、作者等。

源码地址: github.com/biaochenxuy…

其中 VuePressGitBook 的示例代码都在 blog-gitbookblog-vuepress 里面了。

这次需求的结果

令笔者吐血的是:花了 3 天搞的调研,最后 leader 没有采用 😭,还是用回了 功能很重的 wordpress

因为非技术人员要用起来的话,学习成本是比较大的 😂,比如要学 markdown 语法ide 编辑器、基本的打包命令、可能还要学 git ,而非技术人员编辑文档时,一般是用 wps 的 😂。

比较欣慰的是:笔者做完调研后,自己的博客网站也能用上了,哈哈。

最后

推荐阅读GitHub 上能挖矿的神仙技巧 - 如何发现优秀开源项目,估计很多人都不知道的技巧,甚至很多高级工程师都不知道。

参考文章:为你的 VuePress 博客添加 GitTalk 评论