我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!
👈2021 年,你是否曾经幻想着拥有一个属于自己的「知识体系文档」或「面试八股文」手册,却迟迟不知如何下手?
👉2022 年,是该结束这一切臆想了,本文将介绍如何用 VuePress 搭建一个知识文档,跟着我一起实践起来吧!
🚄前言
近几日想将自己的知识体系【技术栈】梳理成文档(文档在手,Offer 我有),方便日后复习所积攒的知识。
但我又不想使用 Halo
再搭建一个同样的博客,那样太乏味了。
🪂如果你还不会用服务器搭建一个网站,不妨看看这篇文章:「最佳实践」如何用服务器优雅地搭建个人博客网站
我对比了网上几种不错的静态网站生成器后,发现使用 VuePress
搭建知识体系框架很合我的胃口!
👑想想有朝一日要面试的时候,与其从网上拉取各类「面经手册」,还不如就从现在起,搭建一个属于自己的「面试八股文」知识体系框架。
🎯VuePress 简介
VuePress 的诞生初衷是尤大大为了支持 Vue 及其子项目的文档需求。难道不觉得 Vue.js 官网和 VuePress 官网出奇地相似吗?
🚀VuePress 生成的页面都是服务端渲染而来的,也因此具有非常好的加载性能和搜索引擎优化(SEO)。同时,一旦页面被加载,Vue 将接管这些静态内容,并将其转换为一个完整的单页应用(SPA),其他页面只会在用户浏览时按需加载。
🥰如果不清楚什么是服务端渲染,可以看这篇文章:彻底理解服务端渲染(SSR)
而且,VuePress 网站是由 Vue
、Vue Router
和 Webpack
驱动的 SPA,如果你熟悉 Vue 知识,甚至可以开发一个自定义主题。
总结下 VuePress 的几个优点:
- 简洁:以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。
- Vue 驱动:享受 Vue + WebPack 的开发体验,可以在 Markdown 中使用 Vue 组件,又可以使用 Vue 自定义主题。
- 高性能:VuePress 会为每个页面预渲染生成静态的 HTML,同时,每个页面被加载的时候,将作为 SPA 运行。
- 内置 Markdown 拓展语法(下文详谈)
- 多语言支持 (
locales
) - 响应式布局
- 支持 PWA 模式
- 强大的 Plugin API
- 基于 Git 的最后更新时间 (
lastUpdated
)
👑VuePress 配置流程
安装
VuePress 需要 Node.js >= 8.6 和 npm / yarn 包管理工具
(1)先检查一下 node 版本
node -v
(2)确认版本没问题后,创建并进入新目录
mkdir interview && cd interview
(3)使用自己习惯的包管理工具进行初始化
npm init # yarn init
(4)将 VuePress 安装为本地依赖
官网建议:不使用全局安装 VuePress
npm install -D vuepress # yarn add -D vuepress
注意:如果你的现有项目依赖了 webpack 3.x,我们推荐使用 Yarn (opens new window)而不是 npm 来安装 VuePress。因为在这种情形下,npm 会生成错误的依赖树。
(5)创建第一篇文档
mkdir docs && echo '# Hello VuePress' > docs/README.md
(6)在 package.json
中添加如下脚本配置
"scripts": {
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
}
(7)本地启动服务器
npm run docs:dev # yarn docs:dev
接下来就可以在 http://localhost:8080/
中查看文档效果了。
如果有遇到乱码也不用紧张,删除 README.md,重新新建一个然后手动输入 # Hello VuePress
即可。
以上流程就完成了 VuePress 的简单安装,但这远远不够,接下来我们来完成一些基本配置。
基本配置(默认主题配置)
提示:这些基本配置仅对默认主题生效,如果使用自定义主题,选项可能会不同。
目录结构
VuePress 遵循 "约定优于配置" 的理念,推荐以下目录结构:
.
├── docs
│ ├── .vuepress (用于存放全局的配置、组件、静态资源等)
│ │ ├── components (该目录中的 Vue 组件将会被自动注册为全局组件)
│ │ ├── theme (用于存放本地主题)
│ │ │ └── Layout.vue
│ │ ├── public (静态资源目录)
│ │ ├── styles (用于存放样式相关的文件)
│ │ │ ├── index.styl
│ │ │ └── palette.styl
│ │ ├── templates (存储 HTML 模板文件)
│ │ │ ├── dev.html
│ │ │ └── ssr.html
│ │ ├── config.js (配置文件的入口文件)
│ │ └── enhanceApp.js (可选的)
│ │
│ ├── README.md (文档首页)
│ ├── guide (存放文章的目录)
│ │ └── README.md
│ └── config.md
│
└── package.json
对于上述的目录结构,默认页面路由地址如下:
文件的相对路径 | 页面路由地址 |
---|---|
/README.md | / |
/guide/README.md | /guide/ |
/config.md | /config.html |
配置站点信息
在 docs
下创建 .vuepress/
文件夹,并在该文件夹下创建 config.js
文件作为配置文件的入口文件
mkdir .vuepress && cd .vuepress && touch config.js
在 docs/.vuepress/config.js
中配置站点信息
module.exports = {
title: 'Interview',
description: "专注于分享后端「面试八股文」, 同时收录算法题的题解分析: 包括但不限于 LeetCode、剑指Offer、PTA...",
}
此时网站出现了标题和搜索栏:
内置搜索栏只会为页面的
h1
、h2
、h3
以及tags
构建搜索索引。如果你需要全文搜索,需要配置添加额外的插件。
首页
在 docs/README.md
下添加首页信息
---
home: true
heroImage: /images/bk.png
heroText: Interview
tagline: put your bio here
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
---
注:要将 bk.png 图片放到 docs/.vuepress/public/images/
静态资源目录下,才能使图片生效,其他静态资源也是如此。
添加首页后的效果:
导航栏
在 docs/.vuepress/config.js
下添加导航栏
// docs/.vuepress.config.js
module.exports = {
themeConfig: {
// 是否启用导航栏
// navbar: false,
nav: [
// 跳转站内页面
{ text: '导读', link: '/guide/foreword/' },
// 嵌套导航
{
text: 'Java',
items: [
{
text: 'JavaSE',
items: [
{ text: '111', link: '/guide/javase/1/' },
{ text: '222', link: '/guide/javase/2/' }
]
},
{
text: 'JavaEE',
items: [
{ text: '111', link: '/guide/javaee/1/' },
{ text: '222', link: '/guide/javaee/2/' }
]
}
]
},
{
text: 'Spring',
items: [
{ text: 'SpringMVC', link: '/guide/springmvc/' },
{ text: 'SpringBoot', link: '/guide/springboot/' },
{ text: 'SpringCloud', link: '/guide/springcloud/' },
]
},
// 跳转站外地址
{ text: '数据结构与算法', link: 'https://leetcode-cn.com/' },
],
}
}
展示下几种导航栏的效果
侧边栏
在 docs/.vuepress/config.js
中添加侧边栏
// docs/.vuepress/config.js
module.exports = {
themeConfig: {
nav: [ xxx ],
sidebar: 'auto'
}
}
⭐ sidebar: 'auto'
会根据文章标题自动生成对应的侧边栏,如下图
🚫但是如果这样设置,文章的数量就被导航栏链接个数限制了(也就是说导航栏的每一个链接仅仅对应一篇文章),这显然不是我们想要的结果。
🤩我们想要的应该是如下这种侧边栏:一个导航栏对应一个系列的文章群,然后每一个侧边栏标题对应一篇文章,这样网站的文章可随时添加,又不会显得导航栏很杂乱!
图片截自卡哥网站
🌈不仅要为不同的页面组显示不同的侧边栏,还想将侧边栏划分为多个组。如何实现?官网给出了答案。
下面我们依葫芦画瓢给出一个可践行的解决方案:
module.exports = {
themeConfig: {
nav: [
{ text: '前言', link: '/guide/foreword/' },
{
text: '数据结构与算法',
items: [
{ text: 'LeetCode', link: '/guide/leetcode/read.md' },
{ text: '剑指Offer', link: '/guide/剑指offer/' },
{ text: 'PTA', link: '/guide/pta/' }
]
},
{ text: 'GitHub', link: 'https://github.com/Wu-yikun' },
],
// sidebar: 'auto', // 不使用默认侧边栏
// 使用自定义侧边栏
sidebar: {
"/guide/leetcode/": getBarLeetCode()
},
},
}
// /guide/leetcode/ 页面组的侧边栏
function getBarLeetCode() {
return [
{
title: 'LeetCode专栏',
collapsable: false,
sidebarDepth: 0,
children: [
"read.md"
]
},
{
title: '数组',
collapsable: false,
sidebarDepth: 0,
children: [
"array/14.最长公共前缀.md",
"array/26.删除有序数组中的重复项.md",
"array/27.移除元素.md",
"array/35.搜索插入位置.md",
"array/66.加一.md",
"array/88.合并两个有序数组.md"
]
},
{
title: '动态规划',
collapsable: false,
sidebarDepth: 0,
children: [
"dp/118.杨辉三角.md",
"dp/119.杨辉三角 II.md",
"dp/121.买股票的最佳时机.md"
]
}
]
}
🔎内部文件目录结构一览:
🥴注意:侧边栏的标题不是根据文件名生成的,而是根据文件中的 h1
标题自动生成的!
更多配置
VuePress 的基本配置还有很多,这里就不逐一例举了。
👨💻VuePress 其他配置参考:vuepress.vuejs.org/zh/theme/de…
多语言支持
VuePress 还可以配置支持多语言:传送门
🧩插件
安装 katex
插件添加公式支持
npm install markdown-it-katex -D
在 docs/.vuepress/config.js
中添加插件配置
module.exports = {
themeConfig: {
nav: [],
sidebar: {},
},
markdown: {
lineNumbers: true,
externalLinks: {
target: '_blank'
},
extendMarkdown: md => {
md.set({
html: true
})
md.use(require('markdown-it-katex'))
}
},
head: [
['link', {
rel: 'stylesheet',
href: 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css'
}],
['link', {
rel: "stylesheet",
href: "https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.10.0/github-markdown.min.css"
}]
]
}
🚀VuePress 插件库:vuepress.vuejs.org/zh/plugin/
🌅Markdown 拓展
因为 Vue 就是以 Markdown 为中心的项目结构,所以支持 Markdown 的所有语法。
此外,VuePress 还额外拓展了一些 Markdown 的用法,类似 GitHub 对 Markdown 的拓展 GFM 一样。
🙄常用的就不提了,我们来说说拓展的语法。
目录
[[toc]]
链接
网站内部的链接,将会被转换成 <router-link>
用于 SPA 导航。同时,站内的每一个文件夹下的 README.md
或者 index.md
文件都会被自动编译为 index.html
,对应的链接将被视为 /
。
内部链接
以如下的文件结构为例:
.
├─ README.md
├─ foo
│ ├─ README.md
│ ├─ one.md
│ └─ two.md
└─ bar
├─ README.md
├─ three.md
└─ four.md
假设你现在在 foo/one.md
中:
[Home](/) <!-- 跳转到根部的 README.md -->
[foo](/foo/) <!-- 跳转到 foo 文件夹的 index.html -->
[foo heading](./#heading) <!-- 跳转到 foo/index.html 的特定标题位置 -->
[bar - three](../bar/three.md) <!-- 具体文件可以使用 .md 结尾(推荐) -->
[bar - four](../bar/four.html#标题) <!-- 也可以用 .html -->
自定义容器
::: tip
这是一个提示
:::
::: warning
这是一个警告
:::
::: danger
这是一个危险警告
:::
::: details
这是一个详情块,在 IE / Edge 中不生效
:::
⭐你也可以自定义块中的标题
::: danger STOP
禁止通行
:::
😓该容器效果默认只对默认主题生效,若要在自定义主题中使用,需要配置插件:vuepress-plugin-container
代码块中的行高亮
```java {3}
class Solution {
public void hello() {
System.out.println("Hello World!");
}
}
```
配置行号
你可以通过配置来为每个代码块显示行号:
module.exports = {
markdown: {
lineNumbers: true
}
}
Yaml Front Matter
VuePress 提供了对 YAML front matter 开箱即用的支持
---
title: Blogging Like a Hacker
lang: en-US
---
这些数据可以在当前 markdown 的正文,或者是任意的自定义或主题组件中使用。
🚎了解更多,请移步:vuepress.vuejs.org/zh/guide/fr…
Emoji
输入
:tada: :100:
输出:🎉 💯
你可以在 Emoji 库中找到所有的 emoji,其实个人建议使用 Window + .
呼出 emoji 库比较方便。
进阶配置 Markdown
VuePress 使用 markdown-it 来渲染 Markdown,上述大多数的拓展也都是通过自定义的插件实现的。
若想要进一步引入其他配置,则可以在 .vuepress/config.js
中修改 markdown
选项:
上文中支持公式的 markdown-it-katex 插件就是按照该方法修改配置的。
module.exports = {
markdown: {
// markdown-it-anchor 的选项
anchor: { permalink: false },
// markdown-it-toc 的选项
toc: { includeLevel: [1, 2] },
extendMarkdown: md => {
// 使用更多的 markdown-it 插件!
md.use(require('markdown-it-xxx'))
}
}
}
🌍部署 GitHub Pages
① 在 docs/.vuepress/config.js
中设置正确的 base
.
- 如果你打算发布到
https://<USERNAME>.github.io/
,则可以省略这一步,因为base
默认是/
。 - 👑如果你打算发布到
https://<USERNAME>.github.io/<REPO>/
(也就是说你的仓库在https://github.com/<USERNAME>/<REPO>
),那么将base
设置为"/<REPO>/"
。
② 在项目目录下新建 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 -
执行脚本即可部署到对应仓库 github pages.
🚀未完待续
😥碎碎念:昨天刚用 VuePress 搭建起一个简易的文档架构,今天肝了一整天的文章对昨天一些具体细节进行复盘,这两天的精力都被榨干了。虽然以上的内容不能全面覆盖 VuePress,但也讲得八九不离十,对付对付还是可以的!
😄相信屏幕前的你也跃跃欲试了,那就赶紧实践起来叭!但要记住一点:网站只是载体,文章才是本体;没有优质的文章,再华丽的 UI 界面设计也只是空壳!
😝由于目前「技术栈」仍然有限,「面试八股文」内容仍未接触,所以我的站点可能还需要 1 年左右才能正式上线,计划开设两个站点:「面试八股文」与「算法小册」。
😉如果你觉得本文有哪些错误或者需要补充的地方,欢迎随时在评论区指正。