嘿,欢迎来到我的博客开发历程分享!这篇文章将带你了解我如何从零开始,使用Docusaurus构建这个你现在正在浏览的个人博客网站。从最初的技术选型纠结,到一步步实现各种功能,再到最终部署上线,我会分享整个过程中的思考、挑战和解决方案。
为什么我最终选择了Docusaurus
说实话,选择一个合适的博客框架真的让我头疼了好一阵子。市面上有太多选择,每个都有各自的优缺点。在做决定之前,我花了不少时间研究和对比了几个主流的静态站点生成器:
我考虑过的其他选择
-
Next.js:
- ✅ 极其强大的React框架,几乎能实现任何功能
- ✅ 支持SSR/SSG/ISR等多种渲染方式
- ❌ 需要从头开始搭建博客功能,工作量大
- ❌ 配置相对复杂,学习曲线陡峭
- ❌ 对于"只是想要一个博客"来说有点大材小用
-
Hugo:
- ✅ 构建速度惊人(Go语言编写)
- ✅ 部署简单,不依赖Node.js环境
- ❌ 使用Go模板语言,不是我熟悉的技术栈
- ❌ 自定义组件相对困难
- ❌ 主题定制需要深入了解Hugo的模板系统
-
Hexo:
- ✅ 专为博客设计,中文社区活跃
- ✅ 主题和插件生态丰富
- ❌ 很多主题质量参差不齐,需要大量修改
- ❌ EJS模板不如React组件灵活
- ❌ 文档质量不够高,有些功能需要自己摸索
-
VuePress/VitePress:
- ✅ 基于Vue生态,界面美观
- ✅ 文档支持良好
- ❌ 主要针对文档网站,博客功能是次要的
- ❌ 我更熟悉React而非Vue
为什么Docusaurus最终胜出
经过一番对比和实验,我最终选择了Docusaurus,主要基于以下几点考虑:
-
React驱动的开发体验:作为一名React开发者,我可以直接利用已有的技能和组件库。不需要学习新的模板语言,直接用JSX就能自定义任何部分。
// 举个例子,我可以轻松创建自定义React组件
function Hero() {
return (
<div className={styles.hero}>
<div className={styles.intro}>
<h1>王起哲的博客</h1>
<p>在这里分享我的技术探索之旅</p>
</div>
</div>
);
} -
开箱即用的完整功能:Docusaurus提供了博客所需的几乎所有功能,包括:
- 文章列表和分类
- 标签系统
- 全文搜索(集成Algolia)
- 代码高亮
- 暗黑模式
- 国际化支持
- SEO优化
这意味着我可以专注于内容和定制,而不是从头实现这些基础功能。
-
MDX的强大表现力:能在Markdown中直接使用React组件是一个巨大的优势。这让我可以在保持内容简洁的同时,在需要的地方添加交互式元素。
# 我的文章标题
这是普通的Markdown内容。
<CodeSandbox slug="react-demo" />
继续写Markdown内容... -
灵活的主题定制机制:Docusaurus的swizzling机制让我可以精确地覆盖和定制任何组件,而不需要fork整个主题。
-
文档与博客的完美结合:我不仅需要写博客文章,还想整理一些技术笔记和教程。Docusaurus的文档+博客双模式正好满足这一需求。
-
活跃的社区和持续维护:由Meta(Facebook)团队维护,更新频繁,文档详尽,这给了我长期使用的信心。
-
性能优化:内置了很多现代Web性能优化,如代码分割、预加载、PWA支持等。
总的来说,Docusaurus提供了一个平衡的解决方案——足够简单,可以快速上手;又足够灵活,能满足各种定制需求。对于像我这样既想要一个漂亮的博客,又希望能充分发挥前端技术的开发者来说,它是一个理想的选择。
开发环境搭建:从零开始的第一步
好啦,既然决定用Docusaurus了,那就赶紧动手搭建环境吧!说实话,刚开始我也是一头雾水,但实际操作起来比想象中简单多了。
前置准备
首先,得确保电脑上装了这些东西(没装的话赶紧补上):
- Node.js:v18或更高版本就行(我用的v18.16.0,老版本可能会有奇怪的问题)
- npm或yarn:我习惯用npm,主要是懒得再装一个yarn😂
- Git:这个必须有,不然后面部署和版本控制会很头疼
创建项目
Docusaurus的脚手架工具真是太方便了,敲一行命令就搞定,完全不用手动配置那堆烦人的东西:
# 创建项目(classic是模板名称)
npx create-docusaurus@latest my-blog classic
# 进到项目目录
cd my-blog
# 启动开发服务器看看效果
npm start
敲完这几行命令后,浏览器会自动打开http://localhost:3000
,然后...哇!一个模板网站就这么出现了!虽然长得有点丑,但基本功能都有了,这就是我喜欢用框架的原因——先跑起来再说,看到成果心里才有底。
不过说实话,这个默认模板离我心目中的博客差得还挺远的,后面得下不少功夫改造它。但至少有个基础,总比从零开始写HTML/CSS强多了,对吧?
项目结构一览
创建好的项目结构大概长这样:
my-blog/
├── blog/ # 博客文章目录(我的文章都扔这里)
├── docs/ # 文档内容目录(不怎么用,但先留着)
├── src/ # 源代码(重头戏在这里)
│ ├── components/ # 自定义React组件(后面会加很多东西)
│ ├── css/ # 样式文件(调整样式的地方)
│ └── pages/ # 自定义页面(首页、关于我之类的)
├── static/ # 静态资源(图片、字体什么的)
├── docusaurus.config.js # 主配置文件(超级重要!)
├── sidebars.js # 侧边栏配置(文档用的,不太管它)
└── package.json # 项目依赖(装插件的时候会动它)
看起来挺多文件的,但别被吓到!实际上大部分时间只会修改其中几个。我刚开始也是一脸懵,但摸索了一会儿就大概知道该去哪里改东西了。
网站配置:开始搭建我的小窝
Docusaurus最让我惊喜的一点就是配置超级简单!所有重要的设置都集中在一个文件里:docusaurus.config.ts
。这对我这种经常忘记"我到底在哪个文件里改过这个设置"的人来说简直是救星。
基础配置
首先得把网站的基本信息改一改,默认的那些placeholder看着就别扭:
const config = {
// 网站标题(浏览器标签上显示的那个)
title: '王起哲的博客',
// 网站URL(部署后的地址,先随便填一个,反正后面会改)
url: 'https://20030727.xyz',
// 基础路径(一般不用动)
baseUrl: '/',
// 网站图标(必须换掉默认的,太丑了)
favicon: 'img/favicon.ico',
// GitHub用户名(用于部署和评论系统)
organizationName: 'wwwqqqzzz',
// 仓库名(就叫blog好了,简单明了)
projectName: 'blog',
// 自定义字段(这个超好用,可以在任何组件里拿到这些数据)
customFields: {
bio: '技术探索之路', // 个人简介
description: '这是王起哲的个人博客,主要分享编程、游戏开发和Web3技术等领域的知识和项目,该网站基于 React 驱动的静态网站生成器 Docusaurus 构建。',
},
// ...还有一堆配置,先不管它们
}
老实说,刚开始我根本不知道这些配置项都是干嘛用的,就是照着文档和别人的博客抄了一遍,然后慢慢调整。有些字段看起来无关紧要,但后面才发现原来它们会影响SEO和社交媒体分享效果!
导航栏与页脚
接下来,我定制了网站的导航栏和页脚,这是用户与网站交互的重要界面元素:
themeConfig: {
// 导航栏配置
navbar: {
logo: {
alt: '王起哲',
src: 'img/logo.webp',
srcDark: 'img/logo.webp',
},
hideOnScroll: true, // 滚动时隐藏导航栏
items: [
{ label: '博客', position: 'right', to: 'blog' },
{ label: '项目', position: 'right', to: 'project' },
{ label: '友链', position: 'right', to: 'friends' },
{ label: '关于', position: 'right', to: 'about' },
{
label: '更多',
position: 'right',
items: [
{ label: '归档', to: 'blog/archive' },
{ label: '技术笔记', to: 'docs/docusaurus-guides' },
{ label: '私密博客', to: 'private' },
],
},
],
},
// 页脚配置
footer: {
style: 'dark',
links: [
{
title: '技术',
items: [
{ label: '博客', to: 'blog' },
{ label: '归档', to: 'blog/archive' },
{ label: '项目展示', to: 'project' },
],
},
{
title: '社交媒体',
items: [
{ label: '关于我', to: '/about' },
{ label: 'GitHub', href: 'https://github.com/wwwqqqzzz' },
],
},
// ...更多链接
],
copyright: `Copyright © 2024 - ${new Date().getFullYear()} 王起哲 | Built with Docusaurus.`,
},
}
这样配置后,我的网站有了清晰的导航结构,用户可以轻松找到各个部分的内容。
博客模式配置
Docusaurus默认是文档优先的,但我想要一个以博客为主的网站。为此,我做了一些特殊配置:
// 在plugins配置中添加自定义博客插件
plugins: [
[
'./src/plugin/plugin-content-blog', // 自定义博客插件路径
{
path: 'blog',
editUrl: ({ locale, blogDirPath, blogPath, permalink }) =>
`https://github.com/wwwqqqzzz/blog/edit/main/${blogDirPath}/${blogPath}`,
editLocalizedFiles: false,
blogDescription: '代码人生:编织技术与生活的博客之旅',
blogSidebarCount: 10,
blogSidebarTitle: '博文',
postsPerPage: 12, // 每页显示的文章数
showReadingTime: true, // 显示阅读时间
readingTime: ({ content, frontMatter, defaultReadingTime }) =>
defaultReadingTime({ content, options: { wordsPerMinute: 300 } }),
feedOptions: { // RSS订阅配置
type: 'all',
title: '王起哲',
description: '个人博客RSS订阅',
copyright: `Copyright © ${new Date().getFullYear()} 王起哲 Built with Docusaurus.`,
},
},
],
// ...其他插件
]
这里我使用了自定义的博客插件,而不是默认的@docusaurus/plugin-content-blog
,这是因为我需要对博客功能进行一些特殊定制,比如将博客数据设置为全局可访问,以便在其他组件中使用。
预设与插件
Docusaurus的强大之处在于它的插件系统。我配置了以下预设和插件:
// 预设配置
presets: [
[
'classic',
{
docs: {
path: 'docs',
sidebarPath: 'sidebars.ts',
},
blog: false, // 禁用默认博客插件,使用自定义插件
theme: {
customCss: ['./src/css/custom.css', './src/css/tweet-theme.css'],
},
sitemap: {
priority: 0.5,
},
gtag: { // Google Analytics配置
trackingID: 'G-S4SD5NXWXF',
anonymizeIP: true,
},
},
],
],
// 插件配置
plugins: [
'docusaurus-plugin-image-zoom', // 图片缩放
'@docusaurus/plugin-ideal-image', // 图片优化
[
'@docusaurus/plugin-pwa', // PWA支持
{
debug: process.env.NODE_ENV === 'development',
offlineModeActivationStrategies: ['appInstalled', 'standalone', 'queryString'],
pwaHead: [
{ tagName: 'link', rel: 'icon', href: '/img/logo.png' },
{ tagName: 'link', rel: 'manifest', href: '/manifest.json' },
{ tagName: 'meta', name: 'theme-color', content: '#12affa' },
],
},
],
[
'vercel-analytics', // Vercel分析
{
debug: process.env.NODE_ENV === 'development',
mode: 'auto',
},
],
// ...其他插件
]
主题定制:让我的博客看起来不那么"模板化"
配置完基本设置后,接下来就是最有趣的部分了——让这个网站看起来像是"我的",而不是千篇一律的Docusaurus默认样式。说实话,默认主题虽然干净,但实在是太...普通了,看起来就像是官方文档。
颜色与样式系统:选择让我心动的蓝色
首先,我得把那个默认的紫色换掉(不是说它不好看,只是不太符合我的风格)。在src/css/custom.css
里,我定义了一套完整的颜色系统:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
/* 设计系统主色调 - 我超喜欢这种蓝色! */
--color-primary-50: #E6F7FF;
--color-primary-100: #BAE7FF;
--color-primary-200: #91D5FF;
--color-primary-300: #69C0FF;
--color-primary-400: #40A9FF;
--color-primary-500: #12AFFA; /* 主色,选了好久才定下来 */
--color-primary-600: #0E9FE5;
--color-primary-700: #0A81BC;
--color-primary-800: #086293;
--color-primary-900: #0B5A82;
/* Docusaurus变量 - 这些必须设置,不然主题会乱套 */
--ifm-color-primary: #12affa;
--ifm-color-primary-dark: #0799e0;
--ifm-color-primary-darker: #0790d4;
--ifm-color-primary-darkest: #0676ae;
--ifm-color-primary-light: #2cb8fa;
--ifm-color-primary-lighter: #39bcfb;
--ifm-color-primary-lightest: #61c9fc;
/* 文本颜色 - 不要用纯黑色,太刺眼了 */
--ifm-text-color: #1F2937;
--ifm-secondary-text-color: #4B5563;
/* 其他全局变量 */
--content-background: #ffffff;
--ifm-navbar-background-color: var(--content-background);
}
/* 暗色模式变量 - 熬夜写代码必备 */
html[data-theme='dark'] {
--content-background: #18181b;
--ifm-color-primary: hsl(214deg 100% 60%); /* 暗模式下蓝色要亮一点 */
--ifm-color-primary-light: hsl(214deg 100% 75%);
/* 文本颜色 - 暗色模式下不要用纯白,太晃眼 */
--ifm-text-color: #F9FAFB;
--ifm-secondary-text-color: #9CA3AF;
/* 背景颜色 - 我喜欢深一点的背景 */
--ifm-background-color: #121212;
--ifm-background-surface-color: #1E1E1E;
/* 博客项样式 - 加点渐变和阴影,看起来更立体 */
--blog-item-background-color: linear-gradient(180deg, #171717, #18181b);
--blog-item-shadow: 0 10px 18px #25374833, 0 0 8px #25374866;
}
}
/* 文章内容样式优化 - 不要太宽,不然读起来累 */
.theme-doc-markdown,
.blog-post-content {
max-width: 780px; /* 经过测试,这个宽度读起来最舒服 */
margin: 0 auto;
}
/* 引用块样式 - 暗色模式下默认的太丑了 */
html[data-theme='dark'] .theme-doc-markdown blockquote,
html[data-theme='dark'] .blog-post-content blockquote {
background-color: rgba(255, 255, 255, 0.05);
}
/* 移动端优化 - 手机上看也要舒服 */
@media (max-width: 768px) {
.theme-doc-markdown,
.blog-post-content {
padding: 0 1rem;
}
.theme-doc-markdown h1, .blog-post-content h1 {
font-size: 1.75rem; /* 手机屏幕小,标题也要小一点 */
}
}
我用了Tailwind CSS来辅助开发,这个工具真是太香了!以前写CSS要想一堆类名,现在直接className="flex items-center justify-between p-4 bg-blue-500"
就搞定了。不过要记住一大堆类名也挺烧脑的,好在有VSCode插件提示。
自定义React组件:打造炫酷的首页
默认的Docusaurus首页实在是太无聊了,我决定完全重写一个。这花了我不少时间,但绝对值得!我创建了一个超酷的Hero组件,带有动画效果和渐变色:
// src/components/landing/Hero/index.tsx
export default function Hero() {
const gridRef = useRef<HTMLDivElement>(null)
const [isMobile, setIsMobile] = useState(false)
// 检测设备类型,手机上要简化一些效果
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768)
}
handleResize() // 先执行一次
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize) // 清理事件
}, [])
return (
<motion.div className={styles.hero}>
{/* 网格背景 - 这个效果我超喜欢 */}
<div ref={gridRef} className={styles.grid_background} />
{/* 手绘装饰 - 增加一点活泼感 */}
<DoodleDecoration />
<div className={styles.intro}>
{/* 标题区域 - 带渐入动画 */}
<motion.div
className={styles.hero_text}
custom={1}
initial="hidden"
animate="visible"
variants={variants}
>
<motion.div className="mb-4 text-xl text-blue-400">
王起哲.dev
</motion.div>
<motion.div className="flex items-center justify-center gap-3">
<span className={styles.name}>全栈开发者</span>
{/* 这个摇晃的手势emoji是我的最爱 */}
<motion.span
className="inline-block text-4xl"
animate={{
rotate: [0, 15, 0], // 左右摇摆
scale: [1, 1.2, 1], // 放大缩小
}}
transition={{
repeat: Infinity, // 无限循环
duration: 1.5,
repeatType: "reverse",
ease: "easeInOut",
}}
>
👋
</motion.span>
</motion.div>
</motion.div>
{/* 简介文字 - 也带动画 */}
<motion.p
custom={2} // 延迟出现
initial="hidden"
animate="visible"
variants={variants}
>
在这里我会分享各类技术栈所遇到问题与解决方案,带你了解最新的技术栈以及实际开发中如何应用,并希望我的开发经历对你有所启发。
</motion.p>
{/* 社交链接 - GitHub、Twitter等 */}
<motion.div
custom={3}
initial="hidden"
animate="visible"
variants={variants}
>
<SocialLinks />
</motion.div>
{/* 按钮 - 带发光效果 */}
<motion.div
custom={4}
initial="hidden"
animate="visible"
variants={variants}
>
<MovingButton
borderRadius={isMobile ? '1rem' : '1.25rem'} // 手机上按钮要小一点
className="relative z-10 flex items-center rounded-2xl border border-solid border-blue-500 bg-blue-500/10 px-4 py-2 text-center text-sm font-semibold text-blue-400 transition-all hover:bg-blue-500/20 hover:shadow-lg md:px-6 md:py-3 md:text-base"
>
<a href="/about" className="font-semibold">
了解更多
</a>
</MovingButton>
</motion.div>
</div>
{/* 底部波浪过渡 - 这个效果做了好久 */}
<motion.div
className={styles.smooth_transition}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: isMobile ? 0.5 : 1, duration: 0.8 }}
>
<div className={styles.transition_wave}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1440 200"
preserveAspectRatio="none"
className={styles.wave_svg}
>
{/* 波浪路径 - 调了好多次才满意 */}
<path
d="M0,160 C240,100 480,180 720,150 C960,120 1200,160 1440,140 L1440,200 L0,200 Z"
fill="var(--ifm-background-color)"
fillOpacity="0.95"
/>
<path
d="M0,180 C320,150 720,190 1200,160 C1280,150 1360,180 1440,170 L1440,200 L0,200 Z"
fill="var(--ifm-background-color)"
fillOpacity="1"
/>
</svg>
</div>
</motion.div>
</motion.div>
)
}
说实话,这个组件写得我头都大了,特别是那个波浪效果,调了好几个小时才满意。Framer Motion这个库真的很强大,但学习曲线也挺陡的,我看了好多教程和例子才搞明白怎么用。
对应的CSS样式文件也花了不少功夫:
/* Hero基础样式 */
.hero {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: calc(100vh - var(--ifm-navbar-height)); /* 占满整个屏幕 */
padding: 4rem 2rem 8rem;
overflow: hidden; /* 隐藏溢出的装饰元素 */
background: linear-gradient(to bottom, rgba(80, 117, 177, 0.1), rgba(80, 117, 177, 0.05)); /* 超淡的渐变背景 */
}
/* 文本和内容样式 */
.hero_text {
text-align: center;
margin-bottom: 2rem;
}
/* 这个渐变文字效果我超喜欢 */
.name {
position: relative;
display: inline-block;
font-size: 3rem;
font-weight: 700;
background: linear-gradient(135deg,
#60A5FA 0%, /* 浅蓝 */
#3B82F6 50%, /* 中蓝 */
#2563EB 100% /* 深蓝 */
);
-webkit-background-clip: text; /* 文字裁剪 */
background-clip: text;
color: transparent; /* 文字本身透明,显示背景 */
line-height: 1.2;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 轻微阴影增加立体感 */
}
/* 手机上的样式调整 - 一定要做好响应式! */
@media (max-width: 570px) {
.hero {
padding: 2rem 1rem 5rem; /* 手机上内边距小一点 */
}
.name {
font-size: 2rem; /* 手机上字体小一点 */
line-height: 1.2;
}
.transition_wave {
height: 100px; /* 波浪高度调整 */
bottom: -5px;
}
}
这个组件是我最满意的部分之一,每次看到它我都有点小骄傲。虽然代码看起来有点复杂,但效果真的很棒!
性能优化组件:让网站飞起来
博客最让人头疼的就是图片加载慢的问题了。我的文章里经常会放不少截图,如果不优化的话,加载体验简直是灾难。所以我专门写了一个图片优化组件:
// src/components/ui/optimized-image.tsx
export function OptimizedImage({
src,
alt = '',
className,
wrapperClassName,
zoomable = false, // 是否可以点击放大
caption,
darkModeOptimized = true, // 暗模式下自动调整亮度
style,
}: OptimizedImageProps): React.ReactElement {
const [isZoomed, setIsZoomed] = useState(false)
const [isLoaded, setIsLoaded] = useState(false) // 跟踪加载状态
// 处理放大/缩小切换
const toggleZoom = () => {
if (zoomable) {
setIsZoomed(!isZoomed) // 点击时切换缩放状态
}
}
return (
<figure className={cn('my-8 overflow-hidden rounded-lg', wrapperClassName)}>
<div
className={cn(
'relative overflow-hidden rounded-lg bg-gray-200 dark:bg-gray-800',
zoomable && 'cursor-zoom-in', // 鼠标变成放大镜
isZoomed && 'cursor-zoom-out', // 已放大时变成缩小镜
)}
onClick={toggleZoom}
>
{/* 预加载背景 - 这个灰色背景超赞,不会出现图片加载时的"闪烁"感 */}
<div
className={cn(
'absolute inset-0 bg-gray-200 dark:bg-gray-800 transition-opacity duration-500',
isLoaded ? 'opacity-0' : 'opacity-100', // 图片加载完成后淡出
)}
/>
{/* 优化图片 - 使用Docusaurus的IdealImage插件 */}
<Image
img={src}
src={src}
alt={alt}
className={cn(
'w-full transition-all duration-500',
// 暗模式下自动调整亮度和对比度,这个功能我超喜欢!
darkModeOptimized && 'dark:brightness-90 dark:contrast-105 dark:hover:brightness-100',
isZoomed ? 'scale-125' : 'scale-100', // 缩放效果
className,
)}
style={{
...style,
transitionProperty: 'opacity, filter, transform',
transitionDuration: '0.5s, 0.5s, 0.5s',
}}
onLoad={() => setIsLoaded(true)} // 图片加载完成时更新状态
/>
</div>
{/* 图片说明 - 可选的 */}
{caption && (
<figcaption className="mt-2 text-center text-sm text-gray-500 dark:text-gray-400">
{caption}
</figcaption>
)}
</figure>
)
}
这个组件看起来简单,但其实解决了好几个问题:
- 懒加载:图片只有滚动到视口内才会加载,节省带宽
- 渐进式加载:先显示占位符,然后平滑过渡到实际图片
- WebP支持:自动使用更高效的WebP格式(文件小30%左右)
- 暗模式优化:暗模式下自动调整图片亮度,不会太暗看不清
- 点击放大:可以放大查看细节,对于截图特别有用
我在写技术文章时经常用这个组件,比如:
<OptimizedImage
src="/img/blog/docusaurus-setup.png"
alt="Docusaurus初始设置界面"
zoomable={true}
caption="Docusaurus初始设置界面(可点击放大)"
/>
这样读者体验好多了,不用忍受图片加载慢或者看不清细节的痛苦。而且代码复用性也很高,一次写好到处用!
内容组织:构建有条理的博客结构
一个好的博客不仅需要漂亮的外观,还需要清晰的内容组织结构。在这方面,我花了不少心思来设计一个既方便我管理,又方便读者浏览的内容结构。
博客文章分类
首先,我将博客文章按主题分类到不同的目录中,这样便于管理和查找:
blog/
├── develop/ # 开发相关文章(编程技巧、框架教程等)
├── lifestyle/ # 生活相关文章(读书笔记、生活感悟等)
├── project/ # 项目记录(个人项目开发过程和心得)
├── reference/ # 年度总结和参考资料
└── authors.yml # 作者信息配置文件
这种目录结构不仅让我在写作时能够更好地组织思路,也方便读者按照自己的兴趣找到相关内容。
文章元数据设计
每篇文章都需要一个元数据区域(frontmatter),用于定义文章的各种属性。我设计了以下格式:
---
title: 个人博客开发记录:从零到Docusaurus
description: 本文记录了我使用Docusaurus构建个人博客的完整过程,包括配置、主题定制、内容组织和部署等环节。
authors: [wqz]
tags: [前端, Docusaurus, 项目]
date: 2024-05-12
image: https://cdn.jsdelivr.net/gh/wwwqqqzzz/Image/img/1746225191887-66abe9fc65a182813698df2d79267bb2.png
slug: blog-development
sticky: 90 # 置顶权重,数值越大越靠前
---
这些元数据不仅用于显示文章的基本信息,还用于实现一些特殊功能:
- tags:用于文章分类和标签页面的自动生成
- image:文章封面图,会显示在文章列表和社交媒体分享中
- slug:自定义URL路径,便于创建更友好的链接
- sticky:置顶功能,让重要文章显示在列表顶部
- authors:作者信息,从
authors.yml
中获取详细资料
自定义静态页面
除了博客文章,一个完整的个人网站还需要一些静态页面。我创建了以下几个重要页面:
src/pages/
├── index.tsx # 首页
├── about.tsx # 关于我
├── project.tsx # 项目展示
├── friends.tsx # 友情链接
└── 404.tsx # 404错误页
这些页面都是使用React组件实现的,而不是简单的Markdown文件,这让我可以实现更复杂的布局和交互效果。例如,项目展示页面使用了卡片网格布局和动画效果:
// src/pages/project.tsx(简化版)
function ProjectPage() {
return (
<Layout title="项目展示">
<div className="container margin-top--lg">
<h1 className="text-center mb-6">我的项目</h1>
<div className="row">
{projects.map((project, i) => (
<motion.div
key={i}
className="col col--4 margin-bottom--lg"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: i * 0.1 }}
>
<ProjectCard
title={project.title}
description={project.description}
preview={project.preview}
website={project.website}
source={project.source}
tags={project.tags}
/>
</motion.div>
))}
</div>
</div>
</Layout>
)
}
导航与发现机制
为了帮助读者更好地发现内容,我实现了多种导航和发现机制:
- 标签系统:每篇文章可以添加多个标签,读者可以通过标签页面浏览相关文章
- 归档页面:按时间顺序展示所有文章,方便查找历史内容
- 相关文章推荐:在文章底部显示相关文章,基于标签相似度计算
- 搜索功能:集成Algolia搜索,支持全文检索
这些功能共同构成了一个完整的内容发现系统,无论读者是有明确目标还是随意浏览,都能找到感兴趣的内容。
插件与功能增强:打造功能丰富的博客体验
一个现代化的博客不仅需要基础的文章展示功能,还需要各种增强功能来提升用户体验。通过Docusaurus强大的插件系统,我为博客添加了多种实用功能。