2026 完整指南:从零搭建 Vue 3 + VuePress 2 个人技术博客(HTTPS/PWA/SEO/广告/评论全栈)
写在前面
这是一篇我用 90 天时间,把一个 2018 年起步的旧博客升级成 2026 版 VuePress 2 站点的完整复盘。
全程踩过的坑:CSP 与广告联盟冲突、PWA 预缓存吞掉新 CSP、PWA 预缓存 404、SAN 证书签发、theme-reco 默认页脚 ICP 不是原生 <a>……一篇文章给你全部答案。
博客线上地址:https://www.lxc666.cn(你正在看的这个站)
1. 为什么选 VuePress 2
2026 年还有人写个人技术博客吗?有,而且活得很好。但选什么框架,主流已经从 5 年前的「Hexo / Hugo」分化出更多选择。我做选型时对比了 4 个主流方案:
| 框架 | 语言 | 主题生态 | 适合人群 | 短板 |
|---|---|---|---|---|
| VuePress 2 | Node.js + Vue 3 | 中文圈丰富(theme-reco、theme-hope) | 前端 / Vue 开发者 | 启动稍慢 |
| Hexo | Node.js | 老牌主题多但偏老 | 老博客迁移 | Vue 3 集成不友好 |
| Hugo | Go | 国际化主题多 | 追求极致构建速度 | 模板语法门槛 |
| Astro | TypeScript | 现代化、支持 React/Vue 组件岛 | 想玩前沿 | 中文资料较少 |
| Next.js | React | App Router + ISR | 同时做应用 + 博客 | 杀鸡用牛刀 |
我选 VuePress 2 的 4 个理由
- 写文章 = 写 Markdown,没有任何额外学习成本;前端基础够用就能改主题。
- Vue 3 原生:可以在 Markdown 里直接写
<MyVueComponent />,组件能力比 Hexo 强很多。 - theme-reco 2.x 的「博客模式」开箱即用:首页 BannerBrand、文章列表、归档时间线、分类标签 4 件套都齐了。
- 构建产物纯静态,扔给 Nginx 就能跑,部署成本几乎为零。
2026
VuePress 2 目前仍在 RC(release candidate)阶段,截至本文写作时最新为 2.0.0-rc.18,theme-reco 为 2.0.0-rc.25。RC 不代表不能用,本博客已经在 rc.18 稳定运行 3 个月 0 崩溃,只是注意锁版本,别 ^2.0.0 这种写法。
2. 环境准备
2.1 Node.js 18+
VuePress 2 的 engines 字段要求 Node 18.16+:
{
"engines": {
"node": ">=18.16.0"
}
}
为什么不是 20 或 22 LTS?因为 2.0.0-rc.x 阶段对 Node 22 的 ESM 加载偶尔有怪问题,Node 18.16 ~ 20.x 是最稳的甜区。
推荐用 nvm-windows 或 fnm 管理多版本:
# Windows
choco install nvm
nvm install 18.20.4
nvm use 18.20.4
node -v # v18.20.4
2.2 包管理器
npm 够用,但如果你电脑磁盘紧张,pnpm 通过硬链接共享依赖能显著节省 node_modules 体积(多项目并行开发时尤为明显):
npm install -g pnpm
本博客统一用 npm,因为后面要配合 patch-package 改主题源码,npm 兼容性最好。
2.3 Git + 仓库
把你的博客托管到 Gitee 或 GitHub。Gitee 国内拉取快(本博客就放 Gitee:luoxuancong/blog),GitHub 配合 GitHub Pages 也方便。
mkdir my-blog
cd my-blog
git init
git remote add origin https://gitee.com/<your-name>/blog.git
3. 项目脚手架
3.1 npm init 三连
npm init -y
npm install -D vuepress@2.0.0-rc.18 vuepress-theme-reco@2.0.0-rc.25
npm install -D @vuepress/bundler-vite@2.0.0-rc.18
npm install vue@^3.5.13
必须锁版本
VuePress 2 的 plugin 和 theme-reco 的版本号必须互相对应(一般保持小版本一致:rc.18 对 rc.61 / rc.25)。不锁版本以后跑 npm install 会被升到新 rc,主题报错你能查到天亮。
3.2 完整目录结构
最终我推荐的项目结构如下:
my-blog/
├── docs/
│ ├── .vuepress/
│ │ ├── config.ts # VuePress 主配置
│ │ └── public/ # 静态资源
│ │ ├── favicon.ico
│ │ ├── logo.png
│ │ ├── ads.txt # AdSense(后面会讲)
│ │ └── js/
│ │ └── baidu.js # 百度统计
│ ├── blogs/ # 所有博客文章
│ │ ├── Vue/
│ │ ├── JavaScript/
│ │ └── AI/
│ ├── about.md # 关于我
│ ├── privacy.md # 隐私政策(AdSense 要求)
│ ├── disclaimer.md # 免责声明
│ └── README.md # 首页
├── patches/ # patch-package 补丁(后面会讲)
├── package.json
└── tsconfig.json
3.3 package.json scripts
{
"scripts": {
"dev": "vuepress dev docs",
"build": "vuepress build docs",
"preview": "vuepress build docs && http-server public -p 8000 -c-1",
"clean": "rimraf docs/.vuepress/.temp docs/.vuepress/.cache public",
"postinstall": "patch-package"
}
}
注意 dest: 'public' 默认会把构建产物放到 docs/.vuepress/dist,我们改到根目录的 public/,部署时直接 rsync public/ server:/var/www/blog/ 一行搞定。
4. 选主题
4.1 三大主题横评
| 主题 | 风格 | 博客模式 | 中文社区 | 我的评分 |
|---|---|---|---|---|
| theme-default | 简洁文档型 | ❌ 需要自己加 | ⭐⭐ | 60 分(纯文档站才选) |
| theme-reco | 博客 + 文档混合 | ✅ 一键开启 | ⭐⭐⭐⭐⭐ | 90 分 |
| theme-hope | 功能最全 | ✅ 内置博客 | ⭐⭐⭐⭐ | 85 分(功能过多反而复杂) |
结论:个人博客首选 theme-reco,功能刚刚好,BannerBrand / Blog / MdContent / Footer 四大模块覆盖 90% 需求。
4.2 安装与启用
npm install -D vuepress-theme-reco@2.0.0-rc.25
docs/.vuepress/config.ts:
import { defineUserConfig } from 'vuepress'
import { viteBundler } from '@vuepress/bundler-vite'
import recoTheme from 'vuepress-theme-reco'
export default defineUserConfig({
lang: 'zh-CN',
title: 'luoxuancong',
description: '前端开发博客 | AI工具教程 — 平安喜乐',
dest: 'public',
bundler: viteBundler(),
theme: recoTheme({
// 头像 / 站点信息 / 导航 / 公告 / 友链 等都在这里配
autoSetBlogCategories: true,
autoSetSeries: true,
})
})
autoSetBlogCategories: true 是关键,它会扫描 docs/blogs/<分类>/xxx.md,自动把目录名变成分类。你不需要在每篇文章 frontmatter 里手写 categories。
5. 5 个必装插件深度配置
这一节是本文最干货的部分。
5.1 @vuepress/plugin-sitemap — SEO 基石
import { sitemapPlugin } from '@vuepress/plugin-sitemap'
sitemapPlugin({
hostname: 'https://www.lxc666.cn',
excludePaths: ['/404.html'],
changefreq: 'weekly',
// 优先用 frontmatter.date,否则回退到 git
modifyTimeGetter: (page) => {
const fmDate = (page.frontmatter as Record<string, unknown>).date
if (fmDate instanceof Date) return fmDate.toISOString()
if (typeof fmDate === 'string') {
const d = new Date(fmDate)
if (!isNaN(d.getTime())) return d.toISOString()
}
const gitTime = (page.data as { git?: { updatedTime?: number } }).git?.updatedTime
return gitTime ? new Date(gitTime).toISOString() : ''
}
})
构建后 public/sitemap.xml 会自动包含所有页面 + lastmod 时间戳。提交给百度站长 / Bing 站长,1-3 天内开始收录。
5.2 @vuepress/plugin-slimsearch — 中文友好的站内搜索
社区常用 @vuepress/plugin-search 但不支持中文分词,搜「Vue 组件」搜不到「Vue 的组件」。slimsearch 用 segmentit 做中文分词,体验完胜:
import { slimsearchPlugin } from '@vuepress/plugin-slimsearch'
slimsearchPlugin({
indexContent: true,
hotReload: false,
suggestion: true,
searchDelay: 200,
queryHistoryCount: 5,
resultHistoryCount: 5,
filter: (page) => page.frontmatter.search !== false
})
构建后会生成 searchIndex-*.js,首次加载约 200KB(gzip 后 ~70KB)。如果你文章很多(>200 篇),可以关掉 indexContent,只索引标题。
5.3 @vuepress/plugin-feed — 一键生成 RSS / Atom / JSON Feed
import { feedPlugin } from '@vuepress/plugin-feed'
feedPlugin({
hostname: 'https://www.lxc666.cn',
atom: true,
json: true,
rss: true,
count: 30,
image: 'https://www.lxc666.cn/logo.png',
channel: {
title: 'luoxuancong 博客',
description: '前端开发博客 | AI工具教程',
copyright: `© ${new Date().getFullYear()} luoxuancong | CC BY-NC-SA 4.0`,
author: { name: 'luoxuancong', url: 'https://github.com/luoxuancong' }
},
// 仅订阅 blogs/ 目录下文章
filter: ({ filePathRelative, frontmatter }) =>
!!filePathRelative
&& filePathRelative.startsWith('blogs/')
&& frontmatter.feed !== false
})
输出 3 个文件:/rss.xml /atom.xml /feed.json,并在 HTML 头部自动注入 <link rel="alternate">,RSS 阅读器可以一键订阅。
5.4 @vuepress/plugin-pwa — 离线访问 + 桌面安装
import { pwaPlugin } from '@vuepress/plugin-pwa'
pwaPlugin({
showInstall: true,
cacheHTML: false, // 关键:HTML 不预缓存(详见踩坑 2)
cacheImage: false, // 不预缓存大图:首次加载更快
maxSize: 1024,
maxImageSize: 512,
themeColor: '#667eea',
favicon: '/favicon.ico',
apple: {
icon: '/logo.png',
statusBarColor: 'black-translucent'
},
update: 'available',
generateSWConfig: {
cleanupOutdatedCaches: true, // 新 SW 激活时清掉上一版整包 precache
runtimeCaching: [
{
urlPattern: ({ request }) => request.destination === 'document',
handler: 'NetworkFirst', // HTML 改走 NetworkFirst:每次都拉最新
options: {
cacheName: 'html-runtime',
networkTimeoutSeconds: 3, // 弱网 3 秒后落回缓存
expiration: { maxEntries: 50, maxAgeSeconds: 7 * 24 * 60 * 60 }
}
}
]
},
manifest: {
name: 'luoxuancong 博客',
short_name: 'LXC Blog',
theme_color: '#667eea',
background_color: '#0a0a1a',
display: 'standalone',
start_url: '/',
icons: [
{ src: '/logo.png', sizes: 'any', type: 'image/png', purpose: 'any' }
]
}
})
踩坑
默认 Nginx 配置写 location = /404.html { internal; },会导致 Workbox 抓不到这个文件,构建后报 bad-precaching-response。
解决:把 internal; 删了,加上 Cache-Control: no-cache:
error_page 404 /404.html;
location = /404.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
access_log off;
}
踩坑
现象:你在 Nginx 给 CSP connect-src 加了一个新域名(例如对接 AdSense 时新增 https://*.adtrafficquality.google),刷新发布后用 curl -I 看响应头明明是新的,但老用户浏览器还是报旧 CSP 拦截,且不会自动好。
根因:cacheHTML: true 让 Workbox 通过 precacheAndRoute 把每张 HTML 的完整响应(含响应头!)存入 Cache Storage。Service Worker 拦截请求后从 Cache 返回,Nginx 改的新 CSP 根本到不了浏览器。即便 /service-worker.js 是 no-cache、新 SW 已经在跑,precache 只在文件 revision hash 变化时才刷新,响应头变化不算 revision 变 —— 这个旧响应可能在用户浏览器里待上几个月。
修复(前面 5.4 节代码已经体现):
| 选项 | 作用 |
|---|---|
cacheHTML: false | HTML 不再进入预缓存清单 |
generateSWConfig.runtimeCaching | 把 request.destination === 'document' 改走 NetworkFirst,每次都尝试新响应 |
generateSWConfig.cleanupOutdatedCaches: true | 新 SW 激活时强制清掉上一版整包 precache |
部署后老用户首次访问会自动激活新 SW + 清旧 precache → CSP 同步生效;想立刻验证就 F12 → Application → Service Workers → Unregister + Clear site data + 硬刷新。
经验沉淀:
| 场景 | 适合 precache 吗 |
|---|---|
| 带 hash 的静态资源(JS / CSS / 图片) | ✅ 完美:内容不变 hash 不变 |
| HTML 页面(路径稳定但响应头 / 内容会动) | ❌ 不要预缓存,走 NetworkFirst |
| Service Worker 自己 | ❌ 强制 Cache-Control: no-cache |
一句话总结:Workbox precache 锁的是「URL + revision」二元组,响应头变化不触发 revision 更新。任何只在 Nginx 加响应头的安全增强,对 cacheHTML=true 的 PWA 都对老用户无效。
5.5 vuepress-plugin-oh-my-live2d — 看板娘装饰
锦上添花的小插件,左下角放一只看板娘小猫:
import { oml2dPlugin } from 'vuepress-plugin-oh-my-live2d'
oml2dPlugin({
dockedPosition: 'left',
models: [
{
path: 'https://model.hacxy.cn/cat-black/model.json',
scale: 0.1,
position: [0, 30],
stageStyle: { height: 280, width: 280 }
}
],
mobileDisplay: false // 移动端隐藏,避免遮挡内容
})
踩坑
官方教程让你用 model.oml2d.com,这个域名 2025 年已过期,所有看板娘模型 404。改用社区维护的 model.hacxy.cn,本博客就在用,稳定。
6. 写文章 / 首页配置
6.1 文章 frontmatter 模板
新建 docs/blogs/Vue/my-first-article.md:
---
title: 我的第一篇 Vue 3 文章
date: 2026-05-12
isOriginal: true
author: 你的名字
description: 一句话概括文章内容,会出现在首页卡片
tags:
- Vue3
- Composition API
sitemap:
priority: 0.9
keywords: Vue3, Composition API, ref, reactive
---
## 1. 引言
正文……
关键字段:
isOriginal: true— theme-reco 会在文章页显示「原创」徽章sitemap.priority— 重要文章给 0.9,普通 0.7keywords— 给搜索引擎的关键词(theme-reco 会注入<meta name="keywords">)tags— 与 categories 分开,更细粒度categories不写:靠autoSetBlogCategories: true用目录名自动归类
6.2 首页 frontmatter(含 ICP 备案号)
docs/README.md:
---
home: true
modules:
- BannerBrand
- Blog
- MdContent
- Footer
bannerBrand:
title: luoxuancong
description: 平安 喜乐
tagline: 专注前端开发 · 分享实用工具
buttons:
- { text: '🚀 开始阅读', link: '/posts.html', type: 'primary' }
- { text: '⏰ 时间线', link: '/timeline.html', type: 'plain' }
socialLinks:
- { icon: 'Github', link: 'https://github.com/your-name' }
footer:
record: 粤ICP备XXXXX号
recordLink: https://beian.miit.gov.cn/
startYear: 2018
---
踩坑
1.x 是 themeConfig.record,2.x 改成了 frontmatter.footer.record,社区很多旧教程没更新。如果你写在 themeConfig 里页脚不会显示。
6.3 让 ICP 链接变成原生 <a>(百度联盟必需)
theme-reco 默认页脚的 ICP 用 <Xicons onclick> 渲染,百度联盟 / 百度爬虫识别不了。需要用 patch-package 改主题源码:
npm install -D patch-package postinstall-postinstall
修改 node_modules/vuepress-theme-reco/lib/client/components/Home/Footer.vue,把 <Xicons> 替换为原生 <a> 标签:
<span class="icp-anchor-wrapper" v-show="frontmatter?.footer?.record">
<component class="xicon-icon" :is="IconSecurity" style="width:18px;height:18px" />
<a
:href="frontmatter?.footer?.recordLink || 'https://beian.miit.gov.cn/'"
target="_blank"
rel="noopener noreferrer"
class="icp-anchor"
>{{ frontmatter?.footer?.record }}</a>
</span>
然后:
npx patch-package vuepress-theme-reco
会在 patches/ 目录生成 vuepress-theme-reco+2.0.0-rc.25.patch。package.json 加上 "postinstall": "patch-package",之后任何机器跑 npm install 都会自动应用补丁。
7. 部署上线
7.1 本地构建
npm run build
# 产物在 public/ 目录
7.2 Nginx 完整配置
服务器:Windows Server + Nginx 1.20,目录 C:\nginx-1.20.2\。
nginx.conf 关键 server block:
# HTTP → HTTPS
server {
listen 80;
server_name www.lxc666.cn lxc666.cn;
# Let's Encrypt 验证目录(必须在 80 端口)
location /.well-known/acme-challenge/ {
root C:/nginx-1.20.2/html;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS 主服务
server {
listen 443 ssl http2;
server_name www.lxc666.cn lxc666.cn;
ssl_certificate C:/nginx-1.20.2/ssl/www.lxc666.cn-chain.pem;
ssl_certificate_key C:/nginx-1.20.2/ssl/www.lxc666.cn-key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root C:/www/blog;
index index.html;
# PWA 修复:404.html 不能用 internal
error_page 404 /404.html;
location = /404.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 静态资源长缓存
location ~* \.(?:css|js|woff2?|png|jpg|svg|gif|ico)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# HTML 不缓存(每次都拉新版)
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
}
7.3 Let's Encrypt + win-acme 自动续签
Windows 上用 win-acme 是最佳选择:
# 下载 win-acme(解压到 C:\win-acme)
# 申请覆盖 www + apex 的 SAN 证书
C:\win-acme\wacs.exe `
--target manual `
--host "www.lxc666.cn,lxc666.cn" `
--commonname "www.lxc666.cn" `
--validation http-01 `
--webroot C:\nginx-1.20.2\html `
--emailaddress your@email.com `
--accepttos `
--installation script `
--script "C:\nginx-1.20.2\reload.bat"
踩坑
早期我只签发了 www.lxc666.cn 的证书,导致 https://lxc666.cn/ 浏览器报「证书不匹配」。
Google AdSense 的爬虫直接访问 apex 域时也会拿不到证书,导致网站验证失败。
解决:--host "www.lxc666.cn,lxc666.cn" 一次签发覆盖两个域名的 SAN 证书。
win-acme 会自动在 Windows 任务计划程序里创建续签任务(每天检查,到期前 30 天自动续)。
7.4 Apex 域处理
很多人配置时只让 www 工作,让 apex 301 跳到 www。但实测时发现,部分 Google AdSense 验证场景下,爬虫并不跟随 301 重定向——如果你绑定的是 apex 域名(如 lxc666.cn),就必须让 apex 直接 200 响应:
# ✅ 正确:两个域名共用同一个 server block,直接 200
server {
listen 443 ssl http2;
server_name www.lxc666.cn lxc666.cn; # 两个域名
# ... 直接服务内容
}
# ❌ 错误:apex 301 到 www,AdSense 可能验证失败
server {
listen 443 ssl http2;
server_name lxc666.cn;
return 301 https://www.lxc666.cn$request_uri;
}
DNS 这一侧也要确认:阿里云 / 腾讯云 DNS 控制台同时给 @ 和 www 加 A 记录,都指向同一台服务器。
8. SEO 全攻略
8.1 三件套自动注入
由插件全自动完成:
- Sitemap →
/sitemap.xml(plugin-sitemap) - RSS / Atom / JSON Feed →
/rss.xml/atom.xml/feed.json(plugin-feed) - PWA manifest →
/manifest.webmanifest(plugin-pwa)
8.2 Open Graph & Twitter Card
config.ts 的 head 字段手动写:
head: [
['meta', { property: 'og:type', content: 'website' }],
['meta', { property: 'og:site_name', content: 'luoxuancong' }],
['meta', { property: 'og:locale', content: 'zh_CN' }],
['meta', { property: 'og:title', content: 'luoxuancong | 前端开发博客' }],
['meta', { property: 'og:description', content: '前端开发博客 | AI工具教程' }],
['meta', { property: 'og:url', content: 'https://www.lxc666.cn' }],
['meta', { property: 'og:image', content: 'https://www.lxc666.cn/logo.png' }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['meta', { name: 'twitter:title', content: 'luoxuancong | 前端开发博客' }],
['meta', { name: 'twitter:description', content: '前端开发博客 | AI工具教程' }],
['meta', { name: 'twitter:image', content: 'https://www.lxc666.cn/logo.png' }]
]
发到微信 / Telegram / Twitter 时会自动展示卡片。
8.3 结构化数据 JSON-LD
帮助 Google / 百度理解站点元信息,提高富片段(Rich Result)出现概率:
['script', { type: 'application/ld+json' }, JSON.stringify({
"@context": "https://schema.org",
"@type": "WebSite",
"name": "luoxuancong 博客",
"url": "https://www.lxc666.cn",
"inLanguage": "zh-CN",
"description": "前端开发博客",
"author": {
"@type": "Person",
"name": "罗玄聪",
"url": "https://github.com/luoxuancong"
}
})]
8.4 CSP 不能阻挡 SEO
Content Security Policy 是必要的安全头,但写得太严会让 Google 抓不到内容、广告跑不起来。本博客实战后的 CSP 模板:
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval'
https://hm.baidu.com
https://pagead2.googlesyndication.com
https://*.googlesyndication.com
https://googleads.g.doubleclick.net
https://adtrafficquality.google
https://*.adtrafficquality.google;
connect-src 'self'
https://comment.lxc666.cn
https://hm.baidu.com
https://pagead2.googlesyndication.com
https://*.googlesyndication.com
https://googleads.g.doubleclick.net
https://www.google.com
https://*.adtrafficquality.google
https://csi.gstatic.com;
img-src 'self' data: https:;
style-src 'self' 'unsafe-inline';
frame-src https://googleads.g.doubleclick.net https://*.googlesyndication.com https://www.google.com https://*.adtrafficquality.google;
" always;
关键技巧
用 *.adtrafficquality.google 通配符可以一次覆盖 ep1.、ep2.、tpc. 等子域名,省得每次 AdSense 出新子域名都改 CSP。
8.5 提交收录
构建上线后,立刻去:
- 百度站长平台:https://ziyuan.baidu.com → 添加网站 → 提交 sitemap.xml
- Google Search Console:https://search.google.com/search-console → 添加资源 → 提交 sitemap
- Bing 站长:https://www.bing.com/webmasters(也是必应中文搜索的来源,别忘)
国内一般 3-7 天百度开始收录,Google 24 小时内能搜到首页。
9. 进阶:让博客真正活起来
到这里你的博客已经可以跑了,但还不够活。这一节讲让博客「有人评论、能赚钱、看着舒服」的最后一公里。
9.1 评论系统 Waline 自建
vuepress-plugin-comments + Waline 是最佳组合,不依赖第三方账号,数据存在自己的 Vercel / 服务器:
- fork Waline 官方仓库
- 用 Vercel 一键部署(数据库选 LeanCloud / Supabase)
- 在
config.ts主题配置里:
commentConfig: {
type: 'waline',
options: {
serverURL: 'https://comment.lxc666.cn', // 自定义域名
pageview: true
}
}
小技巧
给 Waline 绑定自定义域名(如 comment.your-blog.com),可以绕开 vercel.app 域名在国内被墙的问题。
9.2 Google AdSense 接入
简要步骤(详细踩坑记录见本文下半段「踩坑提示框」):
- 申请 Google AdSense 账号,绑定
lxc666.cn - 在
config.ts注入:
['script', {
async: 'true',
src: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXXXXXXXX',
crossorigin: 'anonymous'
}]
- 在
docs/.vuepress/public/ads.txt写入:
google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0
- Nginx CSP 放行 AdSense 域名(参考第 8.4 节)
- 等 1-14 天 Google 内容审核
重要
审核期间务必新增 /privacy.html 和 /disclaimer.html,否则二轮人工审核会被卡。
9.3 百度统计 / Google Analytics
国内访问数据用百度统计(hm.baidu.com),海外用 Google Analytics(gtag)。
百度统计:
// docs/.vuepress/public/js/baidu.js
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?YOUR_BAIDU_ID";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
config.ts 中:
['script', { src: '/js/baidu.js', defer: 'true' }]
9.4 性能优化清单
- ✅ Nginx 开
gzip和brotli(brotli 比 gzip 小 20%) - ✅ 静态资源 30 天缓存 +
immutable - ✅ HTML 不缓存(保证内容及时更新)
- ✅ DNS prefetch 第三方域(
<link rel="dns-prefetch">) - ✅
defer/async加载所有 JS(避免阻塞渲染) - ✅ 关闭 VuePress 自带
prefetch(与 PWA Service Worker 冲突):
export default defineUserConfig({
shouldPrefetch: false,
// ...
})
Lighthouse 跑分目标:性能 ≥ 90、SEO ≥ 95、最佳实践 ≥ 95、无障碍 ≥ 90。
10. 总结 & 完整源码
到这里你的博客应该已经具备:
- ✅ Vue 3 + VuePress 2 + theme-reco 现代化技术栈
- ✅ HTTPS(含 apex 域 SAN 证书 + 自动续签)
- ✅ PWA 离线可用 + 桌面安装
- ✅ 全文搜索(中文分词)
- ✅ RSS / Atom / JSON Feed 订阅
- ✅ Open Graph / Twitter Card / 结构化数据
- ✅ ICP 备案号原生
<a>合规 - ✅ Google AdSense + 百度联盟 接入条件
- ✅ Waline 自建评论
- ✅ Lighthouse ≥ 90
完整依赖清单
{
"engines": { "node": ">=18.16.0" },
"scripts": {
"dev": "vuepress dev docs",
"build": "vuepress build docs",
"postinstall": "patch-package"
},
"devDependencies": {
"@vuepress/plugin-feed": "2.0.0-rc.61",
"@vuepress/plugin-pwa": "2.0.0-rc.61",
"@vuepress/plugin-sitemap": "2.0.0-rc.61",
"@vuepress/plugin-slimsearch": "2.0.0-rc.61",
"patch-package": "^8.0.1",
"vuepress": "2.0.0-rc.18",
"vuepress-theme-reco": "^2.0.0-rc.25"
},
"dependencies": {
"@vuepress/bundler-vite": "2.0.0-rc.18",
"vue": "^3.5.13",
"vuepress-plugin-oh-my-live2d": "^0.19.3"
}
}
参考资料
- VuePress 2 官方文档
- theme-reco 2.x 文档
- Waline 评论系统
- win-acme 文档
- Let's Encrypt
- Google AdSense 帮助
- patch-package 文档
写在最后
我从 2018 年开始写这个博客,最早用的是 Hexo,2021 年换 VuePress 1,2026 年初彻底重写到 VuePress 2 + theme-reco 2.x。这一路最大的感受是:
个人博客不是为了流量,而是为了沉淀。每解决一个工程问题就写一篇,3 年后你会有几百篇带搜索权重的「私人文档」——遇到问题搜自己的博客比翻笔记快多了。
如果你正在搭建第一个博客,希望本文能帮你少走 90 天的弯路。
本站源码:https://gitee.com/luoxuancong/blog(v2 分支)
联系方式:可在 关于我 页面留言、或评论区互动。
—— luoxuancong,2026 年 5 月写于深圳
