Vuepress 搭建静态博客全攻略

image.png

想在两个小时之内搭建出来一个带有评论系统和谷歌数据分析的静态博客,同时完成静态博客的自动构建和部署吗🚀?

这篇文章对每个步骤都做了详细的记录,还把每个步骤中踩过的坑梳理了出来,手把手教你搭建出一个属于你的博客~

后续我还会加上「复制博客文章内容加上版本信息」、「全文检索」等功能,敬请期待💪

博客的最终效果可以这里👉 Vuepress 搭建静态博客全攻略

好了,话不多说,让我们开始吧~

Vuepress 搭建静态博客

可以参照 Vuepress 的官方文档 一步一步来就好了:blush:,我这里就简单说下步骤:

1. 安装 Vuepress

你可以全局安装:

# 可以使用 npm 来全局安装
npm i -g Vuepress

# 也可以使用 yarn 来全局安装
yarn global add Vuepress

也可以安装在你静态博客项目的开发依赖里面:

yarn add --dev Vuepress

# 或者
npm i -D Vuepress

2. 初始化博客项目

# 可以使用 npm 来初始化项目
npm init

# 也可以使用 yarn 来初始化项目
yarn init

然后在项目的根目录下新建一个 docs 文件夹,以后我们写的 markdown 文件都会放在 docs 文件夹下。

我们先随便初始化一个文件来看看效果:

echo '# Hello VuePress!' > docs/README.md

执行命令 vuepress dev docs

可以看到启动了一个页面:


image

为了后续运行方便,我们可以把这些命令写在项目的 package.json 文件里面的 scripts

{
  "scripts": {
    "dev": "vuepress dev docs",
    "build": "vuepress build docs"
  },
 }

3. 进一步的配置

目前我们只写了一个 markdown 文档,所以只有一个页面,后续我们的博客会陆续加入很多内容,肯定需要做目录分级,配置导航栏,可以看文档里的这部分

4. 部署

静态博客搭好了,我们就可以把它部署到服务器上正式给别人访问了,你可以使用 GitHub Pages(GitHub 的静态页面托管服务 )来托管自己的静态博客。
可以使用 gh-pages 来将打包好的静态博客快速部署到 GitHub Pages 上。

同样的,我们可以将部署的命令加入到 package.json 文件里面的 scripts,现在,我们的 scripts 就是这样的:

{
  "scripts": {
    "dev": "vuepress dev docs",
    "build": "vuepress build docs",
    "deploy": "npm run build && gh-pages -d docs/.vuepress/dist"
  },
 }

::: tip 其他第三方静态页面托管服务
也可以使用其他第三方静态页面托管服务(如 Netlify、Coding Pages、Gitlab Pages 等),这篇文章里面介绍了很多免费的静态页面托管服务。
:::

到这一步,你的博客已经可以顺利地运行、构建和部署了,直接执行 npm run deploy 就可以将您的博客部署到 GitHub Pages 上去,如果您还想让你的博客书写和使用的体验更好,可以接着往下看。

GitHub Actions 自动构建/部署

大家有注意到 GitHub 悄悄上线了一个 Actions 功能吗?还不了解的同学可以看这篇文章,写的非常全面。

::: tip GitHub Actions 是什么
GitHub 官方号称 Actions 可以让你的工作流自动化:GitHub 监听某个事件(可能是某个分支的提交),然后触发你预定义的工作流,让大家在GitHub服务器上直接测试代码、部署代码。所以,我们可以利用这里特性来做 CI/CD,开发者只要写一下 workflow 脚本就可以了,不用费心思去想要用哪个第三方的 CI/CD 服务, :100:。
:::

actions 其实就是由一些脚本组成,所以它们是可以复用的,GitHub 做了一个官方市场,可以搜索到他人提交的 actions。另外,还有一个 awesome actions 的仓库,也可以找到不少 action。这样一来,你甚至都不用自己写具体的脚本,直接引用别人的脚本就行啦。

话不多说,赶紧用起来!

写 workflow 脚本

首先我们需要到项目仓库的页面上进入 Actions 这个 tab, 选择 Node 环境进入脚本的编辑页面
[图片上传失败...(image-f14c51-1575913606990)]


image

这里我直接使用了 peaceiris 的 actions-gh-pages,这个 action 可以帮你把打包好的静态文件部署到 GitHub Pages 上去。

最终我的 workflow 脚本如下:
[图片上传失败...(image-b6c39-1575913606990)]
这里有我的脚本源文件,可以参考一下。

更详细的语法可以去看 GitHub Actions 的官方文档

::: warning 注意
因为我用的 action 是第三方的,所以 action 可能会经常更改,如果你是过了一段时间才看到这篇文章,peaceiris 的 actions-gh-pages 很可能已经发生了更新,所以脚本的内容建议直接参照它的官方文档来写。
:::

设置 workflow 的环境变量

上面的脚本里面第21行的环境变量是怎么回事呢?


image

因为我们需要 GitHub Actions 把构建成果发到 GitHub 仓库,因此需要 GitHub 密钥,相当于是给 GitHub actions 授权。

首先运行下面的命令生成一对密钥:

ssh-keygen -t rsa -b 4096 -C "$(git config user.email)" -f gh-pages -N ""
# You will get 2 files:
#   gh-pages.pub (public key)
#   gh-pages     (private key)

然后:

  1. 在博客项目的仓库的 Settings 栏下,找到 Deploy keys这一项,把你的公钥加进去,注意勾选Allow write access
  2. 同样在博客项目的仓库的 Settings 栏下,找到 Secrets这一项,把你的私钥加进去
    [图片上传失败...(image-b39e3d-1575913606990)]

注意事项

  1. Vuepress 作为你的开发依赖加入到项目的 package.json 文件里面进行管理。(否则在 GitHub 的 docker 容器里打包的时候会找不到 Vuepress 这个命令)
  2. 使用 npm 而不是 yarn 来管理依赖包。(因为 npm 是 node 环境自带的包管理工具,无需额外安装,另外, peaceiris 的 actions-gh-pages 也是使用 npm 作为包管理工具的)
  3. 使用 npm ci 来安装依赖包,而不是 npm install

::: tip npm ci 和 npm i 的区别
可以看 medium 上的这篇文章 了解一下。

简单来说就是:不像npm installnpm ci永远不会修改您的package-lock.json,它的使用依赖于 package-lock.json文件。所以如果使用npm ci,您将获得可靠的版本。通常这个命令会在 JenkinsGitLab CI之类的持续集成工具中使用。
:::

好了,这样每次你的项目 master 分支一旦有新的提交,就会自动触发这个 workflow,就可以自动完成静态博客的构建和部署了~

也就是说,我们可以直接利用 GitHub 的 markdown 编辑器,直接新建一个文档进行协作,然后提交到 master 分支就行了,完全不用再次去做 git 提交以及本地的构建和部署,简直太方便了 :rocket:

添加评论系统

搭建博客的目的肯定是为了能和更多技术同好交流,所以评论系统是不可或缺的一个功能。

我们可以使用 gitalk 这个开源的评论插件来做博客的评论系统,它是基于 GitHub Issue 来开发的,可以直接使用 GitHub 账号登录,这对程序员来说真的是相当友好了👬

注册 GitHub OAuth Application

首先要申请一个 GitHub OAuth Application。可以点击这里申请.

image

::: warning 注意
Authorization callback URL 一定要填写当前使用插件页面的域名。
:::

注册成功后你会得到一个 Client ID 和 Client Secret,这两个数据我们下一步要用到。

创建评论组件

我们回到工程,在 docs/.vuepress 下新建一个文件夹 components,再在 components 文件夹下建一个 comment 文件夹,然后新建文件 comment.vue,并复制下面的代码。

<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: 'YOUR_CLINENT_ID',
        clientSecret: 'YOUR_CLINENT_SECRET',
        repo: '此仓库的名称',
        owner: '你的 GitHub 用户名,注意是用户名!!!',
        // 这里接受一个数组,可以添加多个管理员
        admin: ['你的 GitHub 用户名'],
        // id 用于当前页面的唯一标识,一般来讲 pathname 足够了,
       
        // 但是如果你的 pathname 超过 50 个字符,GitHub 将不会成功创建 issue,此情况可以考虑给每个页面生成 hash 值的方法.
        id: location.pathname,
        distractionFreeMode: false,
      };
      const gitalk = new Gitalk(commentConfig);
      gitalk.render('gitalk-container');
    };
  },
};
</script>

::: warning 注意
id 不能超过50个字符,否则后续评论组件初始化的时候会发生 Error:validation failed 的报错。

你可以使用较短的字符来作为 id,例如我自己是使用 document.title.replace(/\s\|\s去冲浪鸭|《|》/g, "") 来作为 id 的,即使用我的文章标题作为 id。
:::

配置组件

在工程根目录下新建一个文件夹 builds,并在里面新建三个文件,分别是 findMarkdown.js, addComponents.js 和 delComponents.js。

findMarkdown.js 文件读取你所有的 Markdown 文件的内容。

// 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

addMarkdown.js 文件将 comment 组件注册到每个 Markdown 文件的最后。

// addMarkdown.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-comment/> \n `, (err) => {
      if (err) throw err
      console.log(`add components to ${dir}`)
    })
  }
}

delMarkdown.js 文件在编译后执行,目的是将每个 Markdown 文件的 comment 组件移除,因为我们只想让 comment 组件打包到编译后的文件中,而非工程文件。

// delMarkdown.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-comment\/> \n /g, ''), (err) => {
      if (err) throw err
      console.log(`del components from ${dir}`)
    })
  })
}

修改构建脚本

修改 build 的脚本:

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

好了,这样你的博客就有一个评论系统了,效果如下:


image

每次有人在一篇评论数为0的文章下面评论,就会自动以当前文章为标题,当前文章的网址为内容生成一条 GitHub Issue,评论就会被关联到这条 GitHub Issue 上。

配置全文搜索

待补充...

配置 Google Analytics

博客搭建好了,也有人访问了,那我们要怎么统计用户的访问情况呢?可以使用谷歌出品的 Google Analytics (GA)。

Google Analytics (GA)是一个对用户活动进行追踪的工具,利用 GA 我们可以收集到博客当前有多少实时活跃用户,博客的总访问量,以及分析用户的一些访问行为,便于我们对博客网站做一些优化,而且它还是免费的!赶快用起来!

下载 google-analytics 插件

Vuepress 官方已经为我们准备好了 google-analytics 插件。

yarn add -D @vuepress/plugin-google-analytics
# OR npm install -D @vuepress/plugin-google-analytics

安装完在 config 配置文件里面配置一下 plugins

module.exports = {
  plugins: [
    [
      '@vuepress/google-analytics',
      {
        'ga': '' // UA-00000000-0
      }
    ]
  ]
}

注册 GA,获取追踪 ID

上面那个 ga ID从哪里获取呢?别着急,我们需要到 Google Analytics 的官网上去注册一下我们的博客应用:


image

进去后选择 web app:


image

[图片上传失败...(image-8dea77-1575913606990)]

把获取到的跟踪ID 填到上面👆的ga这一项里面就好了。

给 Vuepress 博客做 SEO 优化

待补充...

复制文字时显示版权信息

待补充...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342