VuePress + github pages + Travis CI 教程

介绍

VuePress 由两部分组成:一部分是支持用 Vue 开发主题的极简静态网站生成器,另一个部分是为书写技术文档而优化的默认主题。它的诞生初衷是为了支持 Vue 及其子项目的文档需求。
每一个由 VuePress 生成的页面都带有预渲染好的 HTML,也因此具有非常好的加载性能和搜索引擎优化(SEO)。同时,一旦页面被加载,Vue 将接管这些静态内容,并将其转换成一个完整的单页应用(SPA),其他的页面则会只在用户浏览到的时候才按需加载。

快速上手

注意:
请确保你的 Node.js 版本 >= 8。

@全局安装

npm install -g vuepress

注意
全局安装vuepress会和webpack-dev-middleware@3.6.1冲突,导致运行意外报错

构建项目

项目结构

# 新建项目
mkdir my_blog
cd my_blog
# 新建文档目录
mkdir docs 
mkdir docs/.vuepress
# 创建配置文件
touch package.json
touch docs/.vuepress/config.js
# 创建第一个文档
touch docs/README.md

此时项目目录为

my_blog
├─── docs //文档目录
│   ├── README.md //第一篇文档 `hello vuepress`
│   └── .vuepress //主要用于存放VuePress相关的文件
│       └── config.js //VuePress必要的配置文件
└── package.json

配置package.json

VuePress中有两个命令,vuepress dev docs命令运行本地服务,通过访问http://localhost:8080即可预览网站,vuepress build docs命令用来生成静态文件,默认情况下,放置在docs/.vuepress/dist目录中,当然你也可以在docs/.vuepress/config.js中的dest字段来修改默认存放目录。在这里将两个命令封装成脚本的方式,直接使用npm run docs:dev和npm run docs:build即可

{
  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  },
  "dependencies": {
    "vuepress": "^0.14.10"
  },
  "resolutions": {
    "webpack-dev-middleware": "3.6.0"
  }
}

这里手动引入vuepresswebpack-dev-middleware@3.6.0

安装依赖

yarn # 或者  npm I

运行

yarn docs:dev # 或者:npm run docs:dev 
# 全局安装可直接执行 vuepress dev

编译

要生成静态的 HTML 文件,运行

yarn docs:build # 或者:npm run docs:build 
# 全局安装可直接执行 vuepress build

配置默认主题

首页

默认的主题提供了一个首页(Homepage)的布局,
编辑根目录下的README.md文件

---
home: true
heroImage: /hero.png
actionText: 快速上手 →
actionLink: /zh/guide/
features:
- title: 简洁至上
  details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。
- title: Vue驱动
  details: 享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。
- title: 高性能
  details: VuePress 为每个页面预渲染生成静态的 HTML,同时在页面被加载的时候,将作为 SPA 运行。
footer: MIT Licensed | Copyright © 2018-present Evan You
---

导航栏

导航栏可能包含你的页面标题、搜索框、 导航栏链接、多语言切换等等,它们均取决于你的配置。

导航栏链接

可以通过 themeConfig.nav 增加一些导航栏链接

// .vuepress/config.js
module.exports = {
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' },
      { text: 'External', link: 'https://google.com' },
    ]
  }
}

当提供了一个 items 数组而不是一个单一的 link 时,它将显示为一个 下拉列表 :

module.exports = {
  themeConfig: {
    nav: [
      {
        text: 'Languages',
        items: [
          { text: 'Chinese', link: '/language/chinese' },
          { text: 'Japanese', link: '/language/japanese' }
        ]
      }
    ]
  }
}

此外,还可以通过嵌套的 items 来在 下拉列表 中设置分组:

module.exports = {
  themeConfig: {
    nav: [
      {
        text: 'Languages',
        items: [
          { text: 'Group1', items: [/*  */] },
          { text: 'Group2', items: [/*  */] }
        ]
      }
    ]
  }
}

可以使用 themeConfig.navbar 来禁用所有页面的导航栏:

module.exports = {
  themeConfig: {
    navbar: false
  }
}

侧边栏

想要使 侧边栏(Sidebar)生效,需要配置 themeConfig.sidebar,基本的配置,需要一个包含了多个链接的数组:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: [
      '/',
      '/page-a',
      ['/page-b', 'Explicit link text']
    ]
  }
}

可以省略 .md 拓展名,同时以 / 结尾的路径将会被视为 */README.md

嵌套的标题链接

默认情况下,侧边栏会自动地显示由当前页面的标题(headers)组成的链接,并按照页面本身的结构进行嵌套,你可以通过 themeConfig.sidebarDepth 来修改它的行为。默认的深度是 1,它将提取到 h2 的标题,设置成 0 将会禁用标题(headers)链接,同时,最大的深度为 2,它将同时提取 h2 和 h3 标题。

---
sidebarDepth: 2
---

显示所有页面的标题链接

默认情况下,侧边栏只会显示由当前活动页面的标题(headers)组成的链接,你可以将 themeConfig.displayAllHeaders 设置为 true 来显示所有页面的标题链接:

module.exports = {
  themeConfig: {
    displayAllHeaders: true // 默认值:false
  }
}

侧边栏分组

可以通过使用对象来将侧边栏划分成多个组:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: [
      {
        title: 'Group 1',
        collapsable: false,
        children: [
          '/'
        ]
      },
      {
        title: 'Group 2',
        children: [ /* ... */ ]
      }
    ]
  }
}

多个侧边栏

如果你想为不同的页面组来显示不同的侧边栏,首先,将你的页面文件组织成下述的目录结构:

.
├─ README.md
├─ contact.md
├─ about.md
├─ foo/
│  ├─ README.md
│  ├─ one.md
│  └─ two.md
└─ bar/
   ├─ README.md
   ├─ three.md
   └─ four.md

接着,遵循以下的侧边栏配置:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: {
      '/foo/': [
        '',     /* /foo/ */
        'one',  /* /foo/one.html */
        'two'   /* /foo/two.html */
      ],

      '/bar/': [
        '',      /* /bar/ */
        'three', /* /bar/three.html */
        'four'   /* /bar/four.html */
      ],

      // fallback
      '/': [
        '',        /* / */
        'contact', /* /contact.html */
        'about'    /* /about.html */
      ]
    }
  }
}

确保 fallback 侧边栏被最后定义。VuePress 会按顺序遍历侧边栏配置来寻找匹配的配置。

自定义默认主题颜色

如果你只是希望应用一些简单的 overrides 到默认主题的样式上,可以创建一个 .vuepress/override.styl 文件

这里有一些可以调整的颜色变量:

// showing default values
$accentColor = #3eaf7c
$textColor = #2c3e50
$borderColor = #eaecef
$codeBgColor = #282c34

部署到Git

前提

下述的指南基于以下条件:

  • 文档放置在项目的 docs 目录中;
  • 使用的是默认的构建输出位置;
  • VuePress 以本地依赖的形式被安装到你的项目中,并且配置了如下的 npm scripts:
{
  "scripts": {
    "docs:build": "vuepress build docs"
  }
}

准备

  • 前往github,创建用于存放文档的Repo
  • 开启GitHub Pages

SSH Key

ssh,简单来讲,就是一个秘钥,其中,id_rsa是你这台电脑的私人秘钥,不能给别人看的,id_rsa.pub是公共秘钥,可以随便给别人看。把这个公钥放在GitHub上,这样当你链接GitHub自己的账户时,它就会根据公钥匹配你的私钥,当能够相互匹配时,才能够顺利的通过git上传你的文件到GitHub上

生成

git config --global user.name "username"
git config --global user.email "useremail"
ssh-keygen -t rsa -C "1234@qq.com"

回车后提示输入密码, 此处密码可以不填, 直接回车

配置

上述命令运行成功后,终端会给出存储位置

Your public key has been saved in /Users/XXX/.ssh/id_rsa.pub

打开上述文件,复制文件中的公钥添加到github

测试

在gitbash中,查看是否成功

ssh -T git@github.com

开始

  • docs/.vuepress/config.js 中设置正确的 base
    如果你打算发布到 https://<USERNAME>.github.io/,则可以省略这一步,因为 base 默认即是 "/"。
  • 在你的项目中,创建一个如下的 deploy.sh 文件(请自行判断去掉高亮行的注释):
#!/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 -

macOS运行.sh脚本需要权限

chmod 777 deploy.sh

成果

打开XXX.github.io查看成果吧

进阶

在vuepress中使用Vue

自定义Vue组件

所有在 .vuepress/components 中找到的 *.vue 文件将会自动地被注册为全局的异步组件,如:

.
└─ .vuepress
   └─ components
      ├─ demo-1.vue
      ├─ OtherComponent.vue
      └─ Foo
         └─ Bar.vue

你可以直接使用这些组件在任意的 Markdown 文件中(组件名是通过文件名取到的):

<demo-1/>
<OtherComponent/>
<Foo-Bar/>

使用ElementUI

由于 VuePress 是一个标准的 Vue 应用,你可以通过创建一个 .vuepress/enhanceApp.js 文件来做一些应用级别的配置,当该文件存在的时候,会被导入到应用内部。enhanceApp.js 应该 export default 一个钩子函数,并接受一个包含了一些应用级别属性的对象作为参数。你可以使用这个钩子来安装一些附加的 Vue 插件、注册全局组件,或者增加额外的路由钩子等:

export default ({
  Vue, // VuePress 正在使用的 Vue 构造函数
  options, // 附加到根实例的一些选项
  router, // 当前应用的路由实例
  siteData // 站点元数据
}) => {
  // ...做一些其他的应用级别的优化
}

开始

  • 新建.vuepress/enhanceApp.js文件,并引入ElementUI
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
export default ({
                  Vue, // VuePress 正在使用的 Vue 构造函数
                  options, // 附加到根实例的一些选项
                  router, // 当前应用的路由实例
                  siteData // 站点元数据
                }) => {
  // ...做一些其他的应用级别的优化
  Vue.use(Element)
}
  • 安装依赖
    package.json中添加
"dependencies": {
    "element-ui": "^2.7.0"
}
yarn # 或者 npm I
  • MarkDown或者自定义组件中使用ElementUI

Travis CI 持续集成部署

现有问题

我们使用上述的deploy.sh部署到git后,vuepress是把我们项目打包后的静态资源文件pushgit分支上。
上传后的项目大概是这个样子:

vuepress1.png

vuepress2.png

这么做就有一个明显的弊端。如果这个项目不是个人博客,而是需要多人维护的项目文档,那么其他人想要修改这个文档是没办法把这些html文件clone到本地进行修改的。

我们想要的是,git上存放我们的项目,即markdown文件,我们可以随时修改这些markdown然后push到线上,我们的github Pages则会相应的显示编译好的html。

引入

Travis CI正好符合我们的要求。

它的作用是可以监控到我们git资源库的每一次变更,在收到push请求后会为我们提供一个虚拟机来帮助我们执行一些任务,比如我们文档的build以及发布。

这样一来我们把修改好的markdown推到线上后,travis会帮我们自动执行deploy.sh里的脚本。我们就可以只专注于文档本身的内容,也方便文档的维护。。

准备

重命名

使用xxx.github.io作为github Pages首页是无法选择分支的,git会自动将xxx.github.io下的master分支当做静态资源。而我们需要的是master分支存放我们的项目即markdown,另外的分支来存放编译好的html

  • 更改我们的资源库名为docs,新建分支gh pages,然后在设置中将github Pages分支切换到gh pages
    vuepress3.png

设置base

  • 由于文档地址已经更换,这里需要将config.js里的base设置为/docs/
module.exports = {
  base:'/docs/'
}

配置 .travis.yml

然后在项目根目录新建文件 .travis.yml, 这个文件内容根据你的项目而定,比如我们的项目可以是这样的

language: node_js
sudo: required
node_js:
  - "lts/*"
cache:
  directories:
    - node_modules
script:
  - ./deploy.sh
branch: master

修改deploy.sh

  • 集成 travis 还需要我们修改 deploy.sh
#!/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:7revor/7revor.github.io.git master

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

# 如果使用 travis 持续集成
git push -f https://${access_token}@github.com/7revor/docs.git master:gh-pages

cd -

Travis CI配置

监听资源库

  • 使用github账号登录Travis CI,选择需要自动部署的资源库
    vuepress4.png

Access token

  • 首先在githubsetting -> developer setting -> personal access token一栏点击generate new token, 这下面的选项全选,然后就会生成一个token,复制这个token

  • 进入travis后台,在环境变量Environment Variables里设置键值对

    vuepress5.png

测试

将我们的项目push到线上,观察控制台

  • travis已经监听到我们资源库的变化,开始运行虚拟机
    vuepress6.png
  • 执行deploy.sh中的命令
    vuepress7.png
  • 任务执行成功,将build后的文件推送到gh pages分支
    vuepress8.png
  • 面板显示为passed
vuepress9.png

打开xxx.github.io/docs/已经可以正常访问了。

这样我们就实现了master分支存放markdowngh pages存放编译后的静态文件。

如果有新成员加入,直接将master分支clone到本地,修改后推送到远程仓库,travis就会帮我们自动部署。

发布到服务器

我们的需求不止要发布到github Pages,有时也需要发布到自己的服务器。

SSH免密登录

首先要确保自己可以通过ssh命令免密登录自己的服务器,这就需要先生成密钥对

ssh-keygen # 生成密钥对

输入上面的指令以后一路回车即可,你会发现在用户根目录下多了.ssh目录,进去看一下cd ~/.ssh,里面有这3个文件

pubkey.png

id_rsa.pub里的内容,手动复制到服务器的~/.ssh/authorized_keys(如没有可自行创建)中去即可

::: tip 提示
还有一种方法是使用ssh-copy-id root@IP命令,Mac用户可能需要用brew安装一下ssh-copy-idubuntu用户应该是自带的这个命令,实现的效果与上面手动的一样
:::
登录服务器的指令如下,如果不需要密码便进入则表示成功

ssh ${username}@${服务器IP}
login.png

加密

我们要部署到远程服务器,那么势必需要让 Travis 登录到远程服务,那么登录密码怎么处理才能保证安全?这是首先要解决的问题,明文肯定是不行的。

Travis命令行工具

使用Travis命令行工具id_rsa.pub加密,同时将环境变量传至Travis

  • 首先通过 Rubygem 安装 travis
gem install travis

重试了几次发现敲完这段shell如同石沉大海一般,就算开了代理还是纹丝不动,没办法只能换镜像了。

gem update --system
gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/

好了,现在可以愉快的安装 travis

sudo gem install travis
  • 接下来在命令行中登录 Travis
travis login

We need your GitHub login to identify you.
This information will not be sent to Travis CI, only to api.github.com.
The password will not be displayed.

Try running with --github-token or --auto if you don't want to enter your password anyway.

Username: xxx@xxx.xxx
Password for xxx@xxx.xxx: ***
Successfully logged in as demo!

会要求你输入 GitHub 的账号密码,这个是走 GitHub 的服务,所以不用担心密码泄露。

  • 将目录切换到项目根目录下,执行命令
travis encrypt-file ~/.ssh/id_rsa --add

这时在travis的环境变量中会多出两个


en.png

去看一下当前目录下的 .travis.yml,会多出几行

before_install:
  - openssl aes-256-cbc -K $encrypted_d89376f3278d_key -iv $encrypted_d89376f3278d_iv
  - in id_rsa.enc -out ~\/.ssh/id_rsa -d

::: tip 提示
默认生成的命令可能会在/前面带转义符\,我们不需要这些转义符,手动删掉所有的转义符,否则可能在后面引发莫名的错误
:::
为保证权限正常,多加一行设置权限的 shell

before_install:
  - openssl aes-256-cbc -K $encrypted_6dc88f1910e2_key -iv $encrypted_6dc88f1910e2_iv
  -in id_rsa.enc -out ~/.ssh/id_rsa -d
  - chmod 600 ~/.ssh/id_rsa

还有一点可能会用上,因为 travis 第一次登录远程服务器会出现 SSH 主机验证,这边会有一个主机信任问题。官方给出的方案是添加 addons 配置:

addons:
  ssh_known_hosts: your-ip

执行部署脚本

既然已经可以免密登录服务器了,那么写一个部署脚本,在登录时执行该脚本就可以了
.travis.yml 配置文件中写下这么两行:

after_success:
  - scp -o StrictHostKeyChecking=no -r docs/.vuepress/dist/* <USER_NAME>@<HOST_IP>:/home/ubuntu/nginx-server/docs

完整的.travis.yml

language: node_js
sudo: required
node_js:
- lts/*
before_install:
 - openssl aes-256-cbc -K $encrypted_6dc88f1910e2_key -iv $encrypted_6dc88f1910e2_iv
 -in id_rsa.enc -out ~/.ssh/id_rsa -d
 - chmod 600 ~/.ssh/id_rsa
addons:
  ssh_known_hosts: your-ip
cache:
  directories:
  - node_modules
script:
- "./deploy.sh"
branch: master

after_success:
- scp -o StrictHostKeyChecking=no -r docs/.vuepress/dist/* <USER_NAME>@<HOST_IP>:/home/ubuntu/nginx-server/docs

部署测试

提交代码到远程仓库,在Travis查看log,显示成功上传

原文地址

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