我正在参加「掘金·启航计划」
前言
Hexo 是什么?官网的描述是:A fast, simple & powerful blog framework。之前折腾过用Hexo搭建个人技术博客,带有丰富的主题,可以引入RSS、Github 评论系统等。
身为一名前端er,了解到 Evan You 推出了 vitepress -- 基于 Vite 和 Vue 的静态站点生成器,其前身是 vuepress,自带暗黑模式。目前 vitepress 仍处于 alpha 阶段,最新版本是1.0.0-alpha.47,不过可以提前尝鲜一下。
Hexo vs Vitepress
二者的比较如下:
| Hexo | Vitepress | |
|---|---|---|
| 页面基本内容(nav/sidebar/footer) | + | + |
| 自定义页面(首页等) | + | + |
| 友情链接 | + | + |
| 多种主题 | + | + |
| 暗黑模式 | - | + |
| 站内搜索 | + | + |
| RSS | + | - |
| 评论系统 | + | - |
目录结构
docs
FE
test.md
LeetCode
001.md
index.md
.vitepress
config.ts
.gitignore
package.json
node_modules
yarn.lock
package.json
首先是新建package.json文件,内容为:
{
"private": true,
"type": "module",
"scripts": {
"dev": "vitepress dev docs",
"build": "vitepress build docs",
"serve": "vitepress serve docs"
},
"devDependencies": {
"@types/node": "^18.14.0",
"vitepress": "^1.0.0-alpha.47"
}
}
这里需要安装开发依赖 vitepress 和 @types/node 。
其中,@types/node 提供了 Typescript 类型声明。
vitepress 的最新版本是1.0.0-alpha.47,目前是 alpha 内部测试版。一般来说,一个npm包从诞生到最终发布会经历以下几个阶段,参考:Software_release_life_cycle。尽管 vitepress 还处于 alpha 阶段,但是借着 vite 和 vue3 的东风,我们可以看到 vitepress 的功能在不断地完善中,这里拿来尝鲜一下还是不错的。
- Pre-alpha: 功能不完整的版本
- Alpha: 内部版本
- Beta: 公测版本
- Release candidate: 候选版本
- Release to manufacturing (RTM): 生产商发放
- General availability (GA): 一般可用
- Release(Stable): 正式版
docs
docs 目录是主目录,其中的 index.md是首页,.vitepress目录是配置文件所在的目录。我们还可以在此新建更多的 .md 文件或目录。
vitepress 支持 .ts, .cjs, .mjs, .cts, .mts 格式的配置文件。
这里借鉴了官网的配置文件,内容如下:
// config.ts
import { createRequire } from 'module'
import { defineConfig } from 'vitepress'
const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export default defineConfig({
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue powered static site generator.',
lastUpdated: true,
cleanUrls: true,
head: [['meta', { name: 'theme-color', content: '#3c8772' }]],
markdown: {
headers: {
level: [0, 0]
}
},
themeConfig: {
nav: nav(),
sidebar: {
'/FE/': sidebarGuide(),
'/LeetCode/': sidebarConfig()
},
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'Edit this page on GitHub'
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' },
{ icon: 'slack', link: 'https://github.com/vuejs/vitepress' }
],
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2019-present Evan You'
},
algolia: {
appId: '8J64VVRP8K',
apiKey: 'a18e2f4cc5665f6602c5631fd868adfd',
indexName: 'vitepress'
},
carbonAds: {
code: 'CEBDT27Y',
placement: 'vuejsorg'
}
}
})
function nav() {
return [
{ text: 'Front-End', link: '/FE/test', activeMatch: '/FE/' },
{ text: 'LeetCode', link: '/LeetCode/001', activeMatch: '/LeetCode/' },
{
text: pkg.version,
items: [
{
text: 'Changelog',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
},
{
text: 'Contributing',
link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md'
}
]
}
]
}
function sidebarGuide() {
return [
{
text: 'Introduction',
collapsed: false,
items: [
{ text: 'What is VitePress?', link: '/guide/what-is-vitepress' },
{ text: 'Getting Started', link: '/guide/getting-started' },
{ text: 'Configuration', link: '/guide/configuration' },
{ text: 'Routing', link: '/guide/routing' },
{ text: 'Deploying', link: '/guide/deploying' },
{ text: 'Internationalization', link: '/guide/i18n' }
]
},
{
text: 'Writing',
collapsed: false,
items: [
{ text: 'Markdown', link: '/guide/markdown' },
{ text: 'Asset Handling', link: '/guide/asset-handling' },
{ text: 'Frontmatter', link: '/guide/frontmatter' },
{ text: 'Using Vue in Markdown', link: '/guide/using-vue' },
{ text: 'API Reference', link: '/guide/api' }
]
},
{
text: 'Theme',
collapsed: false,
items: [
{ text: 'Introduction', link: '/guide/theme-introduction' },
{ text: 'Nav', link: '/guide/theme-nav' },
{ text: 'Sidebar', link: '/guide/theme-sidebar' },
{ text: 'Prev Next Link', link: '/guide/theme-prev-next-link' },
{ text: 'Edit Link', link: '/guide/theme-edit-link' },
{ text: 'Last Updated', link: '/guide/theme-last-updated' },
{ text: 'Layout', link: '/guide/theme-layout' },
{ text: 'Home Page', link: '/guide/theme-home-page' },
{ text: 'Team Page', link: '/guide/theme-team-page' },
{ text: 'Badge', link: '/guide/theme-badge' },
{ text: 'Footer', link: '/guide/theme-footer' },
{ text: 'Search', link: '/guide/theme-search' },
{ text: 'Carbon Ads', link: '/guide/theme-carbon-ads' }
]
},
{
text: 'Migrations',
collapsed: false,
items: [
{
text: 'Migration from VuePress',
link: '/guide/migration-from-vuepress'
},
{
text: 'Migration from VitePress 0.x',
link: '/guide/migration-from-vitepress-0'
}
]
}
]
}
function sidebarConfig() {
return [
{
text: 'Config',
items: [
{ text: 'Introduction', link: '/config/introduction' },
{ text: 'App Configs', link: '/config/app-configs' },
{ text: 'Theme Configs', link: '/config/theme-configs' },
{ text: 'Frontmatter Configs', link: '/config/frontmatter-configs' }
]
}
]
}
运行
首先,我们需要安装项目依赖,执行yarn;
接着,设置配置文件 .vitepress/config.ts;
然后,编写 .md 文件;
最后,执行 yarn dev 。
由于 vitepress 是基于 vite 的,所以本地运行时,我们很快就将静态的网站跑起来了~
config.ts 详解
我们需要在该文件中设置默认导出:
import { defineConfig } from 'vitepress'
export default defineConfig({
// ...
})
页面配置包括 lang, title, description等:
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue powered static site generator.',
lastUpdated
- Type:
boolean - Default:
false
使用 git commit 信息来获取时间戳。需要注意的是,我们需要将代码提交到 git 仓库后,才会显示时间戳!
设置为 true 后,我们可以看到页面底部显示更新时间:Last updated: 2/22/2023, 8:41:03 PM
cleanUrls
- Type:
boolean - Default:
false
是否允许页面的 URL 不带.html 后缀。
head
数组,可以设置 meta 标签等信息。
markdown
设置 markdown 渲染选项。VitePress 使用 Markdown-it 作为 parser, 使用 Shiki 用于高亮代码。可以在此设置 markdown 渲染选项,比如主题 theme 等。
export default {
markdown: {
theme: 'material-theme-palenight',
lineNumbers: true
}
}
themeConfig
在此自定义主题的样式,比如设置页面的 logo、上方的导航栏 nav、左侧导航栏 sidebar 等。
themeConfig 详解
themeConfig中包含了很多支持自定义的页面内容,详见官方文档。其中,比较重要的配置项是 nav, sidebar, socialLinks, footer 等。
nav
NavItem 数组,用于自定义上方的导航栏。NavItem 包含的字段有:
type NavItem = NavItemWithLink | NavItemWithChildren
type NavItemWithLink = {
text: string
link: string
activeMatch?: string
}
interface NavItemWithChildren {
text?: string
items: NavItemWithLink[]
activeMatch?: string
}
sidebar
SidebarItem 数组,可以自定义左侧导航栏的样式,字段有 text, link, items, collapsed(默认是否折叠):
export type Sidebar = SidebarItem[] | SidebarMulti
export interface SidebarMulti {
[path: string]: SidebarItem[]
}
export type SidebarItem = {
/**
* The text label of the item.
*/
text?: string
/**
* The link of the item.
*/
link?: string
/**
* The children of the item.
*/
items?: SidebarItem[]
/**
* If not specified, group is not collapsible.
*
* If `true`, group is collapsible and collapsed by default
*
* If `false`, group is collapsible but expanded by default
*/
collapsed?: boolean
}
socialLinks
定义外部链接,位于nav导航栏的右侧。这里我们配置了 github 和 slack 两个外部链接:
socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' },
{ icon: 'slack', link: 'https://github.com/vuejs/vitepress' }
],
查看文档,支持的配置内容是:
export type SocialLinkIcon =
| 'discord'
| 'facebook'
| 'github'
| 'instagram'
| 'linkedin'
| 'mastodon'
| 'slack'
| 'twitter'
| 'youtube'
| { svg: string }
footer
配置页面底部的说明信息、版权信息等。比如:
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2019-present Evan You'
},
algolia
- Type:
AlgoliaSearch
我们只需配置 appId, apiKey, indexName 选项,就可以实现站内搜索功能。
Layout
借助 Layout ,我们可以基于 vitepress 内置的样式快速地设置 .md 文件的基本样式。Layout 有以下几种选择:home、doc、page 和 false。不指定时,默认是 doc 。
Home Layout
可以通过设置 hero 或 features 来自定义页面的内容。比如首页的内容如下:
index.md
---
layout: home
title: VitePress
titleTemplate: Vite & Vue Powered Static Site Generator
hero:
name: VitePress
text: Vite & Vue Powered Static Site Generator
tagline: Simple, powerful, and performant. Meet the modern SSG framework you've always wanted.
actions:
- theme: brand
text: Get Started
link: /guide/getting-started
- theme: alt
text: View on GitHub
link: https://github.com/vuejs/vitepress
features:
- title: "Vite: The DX that can't be beat"
details: Feel the speed of Vite. Instant server start and lightning fast HMR that stays fast regardless of the app size.
- title: Designed to be simplicity first
details: With Markdown-centered content, it's built to help you focus on writing and deployed with minimum configuration.
- title: Power of Vue meets Markdown
details: Enhance your content with all the features of Vue in Markdown, while being able to customize your site with Vue.
- title: Fully static yet still dynamic
details: Go wild with true SSG + SPA architecture. Static on page load, but engage users with 100% interactivity from there.
---
预览效果:
Doc Layout
会将全部内容用 .vp-doc 类包裹起来。几乎所有通用的HTML元素如 p 或 h2 会有特殊的样式。
而且,以下功能只会在 Doc 布局下出现:
- Edit Link
- Prev Next Link
- Outline
- Carbon Ads
Page Layout
该布局视为空白页面,页面内容的样式不会受到 vitepress 主题的影响,这有利于自定义页面。
No Layout
设置了layout: false。此布局可以用于自定义加载页面(不包含任何sidebar, navbar 或 footer)。
后记
社区还有用 vitepress 搭建 vue组件库的尝试,其实也跟搭建个人博客的流程差不多。
需要注意的是,vitepress 仍然是alpha阶段,API不稳定、改动较大。不过,不影响 前端er 尝鲜一下。