搭建免费的个人博客网站
1. 概述
静态博客工具可以把 Markdown 文档构建成可部署的网站,并提供代码高亮、目录、Frontmatter、图片资源管理等常用能力。
常见选择包括 VuePress、VitePress、Hugo、Jekyll、Hexo 和 Docsify。
整体流程很简单:选择博客框架,编写 Markdown,构建静态页面,再部署到个人服务器或第三方静态托管平台。
本文以基于 VitePress 和 Teek 的博客项目为例,整理本地写作、图标规范、图片管理、Algolia 搜索集成,以及部署到 Cloudflare Pages、Netlify 与 Gitee Pages 的完整步骤。
2. 本地环境搭建
2.1. VitePress
根据 VitePress 官方文档 初始化项目,再参考 Teek 主题文档 完成主题接入。项目初始化后,建议先确认本地构建命令可以正常运行,再继续配置图片、图标和部署平台。
2.2. IDE
本地可以安装 Typora 或 VS Code 作为 Markdown 编辑器。
Typora 对 Markdown 图片、表格和图床集成比较友好,适合日常写作和截图整理。
2.3. 图床
浏览器默认会限制 https 页面加载 http 图片资源。选择图床时,优先确认图片外链是否支持 https。如果确实需要临时加载 http 图片,可以在浏览器中手动配置:隐私和安全 -> 更多内容设置 -> 不安全内容 -> 允许显示不安全内容。

可用于存储博客图片,并生成外链地址。
集成 Typora

定期备份
第三方图床存在访问失败或服务调整的可能,重要图片建议定期备份。
- 复制图片 URL。

- 运行脚本下载到本地。
sh# 图片URL列表 urls=("https://pic.imgdb.cn/item/65f5b2bd9f345e8d03f022c0.png" "https://pic.imgdb.cn/item/65f5b2679f345e8d03ed0734.png") # 循环下载 for url in "${urls[@]}"; do filename=$(basename "$url") curl -o "./$filename" --location --request GET "$url" \ --header "Host: pic.imgdb.cn" \ --header "Connection: keep-alive" \ --header "Referer: $url" done
项目目录
也可以直接将图片存放在当前 Markdown 同级的
assets目录。Typora 中开启复制图片到 ./assets 文件夹后,截图和本地图片会自动归档到文章目录下。
2.4. 图标
博客中的导航、卡片、标题、目录和资源清单都需要图标。当前项目已经注册统一组件 AppIcon,底层封装 Teek 官方 TkIcon,页面里直接使用即可。
图标选择遵循一个原则:通用语义优先用 Emoji,品牌和技术 Logo 再用本地资源或 Iconify 离线集合补充,避免同一页面出现过多风格。
当前支持清单:
| 图标源 | 是否启用 | 用途 |
|---|---|---|
| Emoji | 是 | 默认主风格,适合导航、标题、目录、卡片和通用语义。 |
| 本地 SVG/PNG | 是 | 平台 Logo、项目 Logo、公司 Logo、MyBatis 这类缺口图标。 |
| Logos | 是 | MySQL、Redis、Nginx、Kafka 等官方或开源项目 Logo。 |
| Devicon | 是 | Java、Jenkins 等编程语言、运行时和开发工具 Logo。 |
| Skill Icons | 是,少量使用 | Spring、Docker、Linux、Maven 等技术栈补充。 |
| Simple Icons | 是,少量使用 | 知乎等社交平台或品牌图标补充,本地 SVG 优先。 |
| Iconfont.cn 离线文件 | 是,作为备选接口 | 兼容后续导出的自定义图标,统一使用 Symbol 模式。 |
2.4.1. 推荐目录
src/public/assets/icons/ # 本地 SVG / PNG,例如 MyBatis、私有项目 Logo
src/public/assets/iconfont/ # Iconfont.cn 导出的 iconfont.js
src/.vitepress/theme/icons/aliases.ts # 图标别名统一维护
src/.vitepress/theme/icons/iconify.ts # 从已安装的 @iconify-json/* 依赖读取离线图标
src/.vitepress/theme/icons/local.ts # 本地 SVG / PNG 路径规则日常按这个优先级选择:
emoji:xxx:默认选择,适合通用语义,保持站内风格统一。img/ 本地 SVG:适合平台、公司、项目 Logo,避免品牌图标来源重复。logos/devicon/skill-icons/simple-icons:只作为官方/开源/技术 Logo 补充。iconfont:适合 Iconfont.cn 离线导出的补充图标,本站统一解析为 Symbol 模式。iconifyOffline:适合少量手写或单独传入的 Iconify 图标对象。
2.4.2. 基础用法
<AppIcon icon="emoji:📝" />
<AppIcon icon="/assets/logo/jerry-up/project-blog.svg" />
<AppIcon icon="local:/assets/icons/custom.svg" />
<AppIcon icon="iconfont:MyBatis" />
<AppIcon icon="logos:mysql-icon" />
<AppIcon icon="devicon:java" />普通页面、组件和 Frontmatter 不直接写底层图标源,先把可复用图标收进别名表:
<AppIcon icon="site-notes" />
<AppIcon icon="mysql" />
<AppIcon icon="java" />
<AppIcon icon="mybatis" />页面、侧边栏和目录卡片的图标写在文档 Frontmatter 中:
---
title: 搭建免费的个人博客网站
icon: vitepress
---正文标题和右侧目录图标写在标题末尾:
## 本地环境搭建 {icon="settings"}
### VitePress {icon="vitepress"}
### Iconfont Symbol 示例 {icon="iconfont:icon-iconfont"}{icon="..."} 不会显示在标题文字里,只作为渲染图标的数据来源。
如果图标会被重复使用,优先写进别名表:
// src/.vitepress/theme/icons/aliases.ts
export const iconAliases = {
mybatis: "iconfont:MyBatis",
github: "logos:github-icon",
java: "skill-icons:java-light",
};页面中就可以简化为:
<AppIcon icon="mybatis" />
<AppIcon icon="github" />
<AppIcon icon="java" />2.4.3. 支持类型样例
下面展示本站启用的图标类型。Iconfont.cn 只保留 symbol 样例;iconifyOnline 不作为运行时样例渲染。
2.4.4. 不同平台样例
下面这些都走 AppIcon 的统一入口。卡片标题可以点击跳转到对应官网或资源地址。Iconify 只展示本站允许的 Logo 类集合;通用语义继续使用 Emoji。
2.4.5. 安装图标库依赖
只有 Iconify 集合需要安装对应的 @iconify-json/{prefix} 依赖。当前项目会先把已引用的 Iconify 图标导出为静态 SVG;静态目录没有命中时,再从本地依赖读取 icons.json 并用 iconifyOffline 兜底渲染。Emoji、Iconfont.cn、本地图片和本地 SVG 不需要 npm 包。
| 来源 | 地址规则 | 用途 |
|---|---|---|
| Iconify 图标集 | https://www.npmjs.com/package/@iconify-json/{prefix} | 某个平台的离线 JSON npm 包。 |
| 单个 SVG | https://api.iconify.design/{prefix}/{name}.svg | 仅用于人工核对或临时获取,不参与运行时加载。 |
| Iconfont.cn | https://www.iconfont.cn/ | 在 Iconfont 项目中导出 symbol 离线文件。 |
| 本地图片/SVG | 项目内 /assets/... 路径 | 已经是本地资源,无需在线下载。 |
pnpm add -D @iconify-json/logos @iconify-json/devicon @iconify-json/skill-icons @iconify-json/simple-icons新增或调整 Iconify 图标后,重新导出静态资源和清单:
pnpm run icons:export安装后先收敛到别名,再在页面使用别名:
<AppIcon icon="mysql" />
<AppIcon icon="java" />
<AppIcon icon="docker" />当前项目只保留这四类 Iconify 集合:
https://www.npmjs.com/package/@iconify-json/logos
https://www.npmjs.com/package/@iconify-json/simple-icons
https://www.npmjs.com/package/@iconify-json/devicon
https://www.npmjs.com/package/@iconify-json/skill-icons2.4.6. 本地离线加载控制
当前项目只使用本地离线图标。样例中的 在线 链接只用于人工核对,客户端渲染不会读取 api.iconify.design。
| 写法 | 加载方式 | 示例 |
|---|---|---|
emoji:xxx | 本地文本渲染,不请求资源 | <AppIcon icon="emoji:📝" /> |
/xxx.png、local:/xxx.svg、img:/xxx.png | 本地图片资源 | <AppIcon icon="local:/assets/icons/custom.svg" /> |
iconfont:xxx | 本地 Iconfont.cn Symbol 文件 | <AppIcon icon="iconfont:MyBatis" /> |
:icon="offlineIcon" + icon-type="iconifyOffline" | 本地打包的 Iconify 数据 | <AppIcon :icon="offlineIcon" icon-type="iconifyOffline" /> |
平台:图标名 | 优先走静态 SVG,缺失时回退到本地 Iconify JSON | logos:mysql-icon -> /assets/icons/logos/mysql-icon.svg |
| 别名 | 由 aliases.ts 决定 | mybatis -> iconfont:MyBatis |
平台样例里的 在线 链接使用 Iconify API 的 SVG 直链,例如 https://api.iconify.design/logos/mysql-icon.svg,只用于核对图标长什么样。项目中的 <AppIcon icon="mysql" /> 会通过别名解析到 logos:mysql-icon,优先命中静态文件 /assets/icons/logos/mysql-icon.svg;如果静态清单中没有这个图标,再读取本地依赖 node_modules/@iconify-json/logos/icons.json 兜底渲染。
远程图片地址也不会作为图标加载,例如 https://example.com/icon.svg 会被忽略。需要使用时先下载到 src/public/assets/icons/,再通过 local:/assets/icons/... 引用。
只要使用 平台:图标名 写法,就必须安装对应依赖包。依赖不存在或图标名称写错时,图标会留空,不会回退到在线请求。当前允许的本地依赖如下:
src/public/assets/icons/{collection}/{name}.svg
src/.vitepress/theme/icons/static.ts
node_modules/@iconify-json/logos/icons.json
node_modules/@iconify-json/devicon/icons.json
node_modules/@iconify-json/skill-icons/icons.json
node_modules/@iconify-json/simple-icons/icons.json少量高频图标可以继续通过别名映射到本地,适合 MyBatis、项目 Logo、平台 Logo 等需要统一维护的场景。
// src/.vitepress/theme/icons/aliases.ts
export const iconAliases = {
java: "skill-icons:java-light",
github: "logos:github-icon",
mybatis: "iconfont:MyBatis",
};<AppIcon icon="java" />简单说:local:/、/assets/、iconfont:、iconifyOffline、logos:、devicon:、skill-icons:、simple-icons: 都是本地离线加载。logos: 等平台写法优先使用 src/public/assets/icons/ 下的静态 SVG,缺失时才回退到本地 npm 图标数据。文档中的在线 SVG 地址只用于人工核对,不参与客户端渲染。
2.5. 搜索
VitePress 默认主题搜索支持本地搜索,也支持接入 Algolia DocSearch 做在线全文检索。个人博客文章逐渐变多后,Algolia 的优势是索引独立、搜索体验成熟、可以在后台查看索引记录和搜索效果。
Algolia 集成可以按四步理解:创建应用和索引,配置 Crawler 抓取公开站点,把 Application ID / Search-Only API Key / Index Name 写进 VitePress,最后部署并运行爬虫验证。
| 步骤 | 操作 | 产物 |
|---|---|---|
| 1 | 在 Algolia 创建 Application 和 Index | appId、indexName |
| 2 | 在 Crawler 中添加公开站点地址 | 可定时抓取的爬虫任务 |
| 3 | 在 VitePress 中切换 provider: "algolia" | 前端搜索框接入 Algolia |
| 4 | 部署站点并运行一次 Crawl | 搜索弹窗能搜到文章 |
Crawler 需要能访问公开页面。建议先完成一次 Cloudflare Pages 或 Netlify 部署,再回到 Algolia 配置域名和爬虫。
2.5.1. 创建 Algolia 应用和索引
登录 Algolia Dashboard,创建一个新的 Application。

在应用内创建 Index,命名建议和站点保持一致,例如
jerry-up-blog。textApplication: jerry-up Index Name: jerry-up-blog
进入
Settings -> API Keys,记录这三个值。字段 用途 是否可以放到前端 Application IDVitePress 和 Crawler 都需要 是 Search-Only API Key前端搜索时读取索引 是 Admin API KeyCrawler 写入索引 否 密钥边界Search-Only API Key会出现在前端配置里,这是正常的。Admin API Key只能放在 Algolia Crawler 后台,不要写进仓库。
2.5.2. 配置 Crawler 抓取站点
Algolia 的搜索框只负责查询,真正把文章写进索引的是 Crawler。进入 Algolia Crawler,先添加博客域名并完成验证,再创建一个新的 Crawler 任务。
添加站点域名,
Start URL填写博客首页。texthttps://jerry-up-blog.pages.dev
选择一种验证方式。个人博客最常用的是
HTML file、Meta tag或DNS TXT。验证方式 适合场景 HTML file可以上传静态文件到站点根目录 Meta tag可以修改 VitePress head配置DNS TXT域名在自己手里,且能修改 DNS 记录 如果选择
Meta tag,可以在.vitepress/config.mts中统一维护head。验证码最终会公开在页面源码里,可以直接写在配置常量中;环境变量只作为临时覆盖手段:tsimport { defineConfig } from "vitepress"; const getEnvValue = (key: string): string => process.env[key]?.trim() ?? ""; const algoliaPublicConfig = { siteVerification: "ALGOLIA_SITE_VERIFICATION_CODE", }; const algoliaSiteVerification = getEnvValue("ALGOLIA_SITE_VERIFICATION") || algoliaPublicConfig.siteVerification; const siteHead: [string, Record<string, string>][] = [ ["link", { rel: "icon", href: "/favicon.svg", type: "image/svg+xml" }], ...(algoliaSiteVerification ? [["meta", { name: "algolia-site-verification", content: algoliaSiteVerification }] as [string, Record<string, string>]] : []), ]; export default defineConfig({ head: siteHead, });需要临时替换验证码时,macOS / Linux 可以这样启动:
shALGOLIA_SITE_VERIFICATION=ALGOLIA_VERIFICATION_CODE pnpm run devWindows PowerShell 可以这样启动:
powershell$env:ALGOLIA_SITE_VERIFICATION="ALGOLIA_VERIFICATION_CODE"; pnpm run dev如果已经把验证码写进配置常量,部署到 Cloudflare Pages 或 Netlify 时不需要再设置
ALGOLIA_SITE_VERIFICATION。只有临时替换验证码时,才把它加到构建环境变量里再重新部署。构建时可以用下面的命令确认最终页面会带上 Meta tag。当前仓库的真实脚本是
build,不要写成blog:build。shpnpm install && pnpm run build如果想在本地构建时临时替换验证码,macOS / Linux 使用:
shALGOLIA_SITE_VERIFICATION=ALGOLIA_VERIFICATION_CODE pnpm run buildWindows PowerShell 使用:
powershell$env:ALGOLIA_SITE_VERIFICATION="ALGOLIA_VERIFICATION_CODE"; pnpm run build
域名验证通过后,回到 Crawler 控制台,点击
New crawler创建爬虫任务。验证后还要新增 Crawler域名验证只说明站点归属可确认,不会自动创建索引任务。验证成功后需要再新增一个 Crawler,并把它绑定到当前 Application、站点地址和目标 Index。
推荐按下面的方式填写,字段名称以 Algolia 页面实际展示为准:
配置项 建议值 说明 Crawler namejerry-up-blog-crawler方便和博客项目对应 Application当前 Algolia Application 使用前面创建的应用 Start URLhttps://jerry-up-blog.pages.dev/填线上博客首页 Index namejerry-up-blog和 VitePress indexName保持一致ConfigurationJavaScript config/Manual setup方便直接粘贴下面的规则 博客文档推荐内容类型优先选择 Technical documentation 和 Articles;Template 优先选择 VitePress / Vitepress;Products 不勾;General web pages 只有在需要搜索首页、关于页、项目页时再勾选。
如果页面出现
What types of content do you want to crawl?,它是在问站点里主要有哪些内容类型。这个选择通常用于生成初始抓取模板,后续仍然可以在 Crawler 配置中通过actions、pathsToMatch和recordExtractor精细控制。选项 作用 和其他选项的区别 推荐策略 General web pages抓取普通网站页面,例如首页、关于页、项目介绍页、导航页、活动页 关注整页内容,不假设页面一定有文章时间线、商品字段或文档层级 按需勾选。需要让首页、关于页、推荐页、项目页进入搜索时再选;只做文档搜索可以不勾 Products抓取商品或服务条目,例如名称、价格、分类、库存、SKU、商品描述 面向电商或产品目录,重点是结构化商品属性,不适合普通博客文档 不勾。博客文档没有商品、价格、库存、SKU 这类模型 Articles抓取文章内容,例如博客、资讯、经验总结、排障记录、更新日志 面向按时间发布的内容,通常更关注标题、摘要、作者、发布时间和正文 推荐勾选。日常积累、排障记录、经验总结属于这一类 Technical documentation抓取技术文档、教程、安装手册、API/配置说明、问题排查步骤 面向有目录层级的文档,通常按 h1/h2/h3、正文段落、列表和代码块生成搜索记录优先勾选。安装手册、应用使用说明、模板代码、环境搭建文档属于这一类 内容类型选择如果是多选,优先勾选 Technical documentation 和 Articles;General web pages 视搜索范围决定;Products 不勾。这样搜索结果会优先覆盖技术文档和排障文章,避免混入商品类模板。
如果向导只能单选,优先选择
Technical documentation。博客文档的核心价值是目录化阅读、安装说明和问题排查,文章内容也可以在后续 Crawler 配置中继续覆盖。接着遇到
Template *时,它是在问 Crawler 用哪一种站点生成器的初始抓取模板。模板会预填startUrls、sitemaps、pathsToMatch、正文选择器和搜索索引字段,但它只是起点,创建后仍然可以在Editor里替换成下方配置。Template 选项 适合场景 推荐策略 VitePress/VitepressVitePress 站点,正文通常在 .content容器里,标题按h1/h2/h3分层首选。VitePress + Teek 项目和下方配置规则最接近 VuePressVuePress 站点,正文容器和侧边栏选择器与 VitePress 不同 不选。名字接近但选择器不完全一致 DocusaurusDocusaurus 站点,通常用 article h1/h2、Docusaurus 菜单类名不选。模板会偏向 Docusaurus DOM Default没有匹配框架,或只是想先创建 Crawler 再手动改配置 备选。如果页面没有 VitePress,就选Default,创建后进入Editor粘贴下面的配置其他框架模板 Astro Starlight、Rspress、pkgdown 等对应框架 不选,除非站点实际迁移到了对应框架 Template 选择优先选择 VitePress / Vitepress。没有这个选项时选择 Default,创建后进入 Editor,把配置替换为下面这段 Crawler 配置。不要选 VuePress 或 Docusaurus,它们和博客文档的 DOM 结构不同。
官方 VitePress 模板的核心思路是使用
.content h1、.content h2、.content h3和.content p, .content li抽取文档层级与正文。下方配置也沿用这个思路,并额外移除了侧边栏、导航和页脚,避免搜索结果里混入导航文字。如果页面提供可视化配置,也可以先创建 Crawler,再进入
Configuration或Editor页面改成下面的 JavaScript 配置。关键是最终要能看到一个独立的 Crawler 任务,并且它指向jerry-up-blog这个 Index。
在 Crawler 配置中写入抓取规则。VitePress 官方示例使用
.content h1、.content h2、.content p等选择器,适合默认文档布局。如果站点暂时没有sitemap.xml,先删除sitemaps这一行,等后续生成站点地图后再补回来。jsnew Crawler({ appId: "YOUR_APP_ID", apiKey: "YOUR_ADMIN_API_KEY", rateLimit: 8, startUrls: ["https://your-domain.com/"], sitemaps: ["https://your-domain.com/sitemap.xml"], discoveryPatterns: ["https://your-domain.com/**"], exclusionPatterns: [ "https://your-domain.com/tags/**", "https://your-domain.com/categories/**", "https://your-domain.com/archives/**", ], renderJavaScript: false, actions: [ { indexName: "jerry-up-blog", pathsToMatch: ["https://your-domain.com/**"], recordExtractor: ({ $, helpers }) => { $(".VPDocAside, .VPSidebar, .VPNav, .site-footer").remove(); return helpers.docsearch({ recordProps: { lvl0: { selectors: ".content h1", defaultValue: "博客文档", }, lvl1: ".content h1", lvl2: ".content h2", lvl3: ".content h3", lvl4: ".content h4", lvl5: ".content h5", content: ".content p, .content li", }, indexHeadings: true, }); }, }, ], });
保存配置后运行一次测试抓取。抓取完成后,进入 Index 页面确认有 records。
textRecords > 0
2.5.3. 修改 VitePress 搜索配置
打开 .vitepress/config.mts,把 Algolia 前端搜索参数收敛到公共配置常量中。appId、searchApiKey、indexName 三个值都存在时使用 Algolia;缺少任意一个时回退到本地搜索,避免本地开发或临时部署时搜索不可用。
import { defineConfig, type DefaultTheme } from "vitepress";
const getEnvValue = (key: string): string => process.env[key]?.trim() ?? "";
const algoliaPublicConfig = {
appId: "B2S5VC6T26",
searchApiKey: "7842783a4e6cb13827082894378549d3",
indexName: "jerry-up-blog",
};
const algoliaAppId = getEnvValue("ALGOLIA_APP_ID") || algoliaPublicConfig.appId;
const algoliaSearchApiKey = getEnvValue("ALGOLIA_SEARCH_API_KEY") || algoliaPublicConfig.searchApiKey;
const algoliaIndexName = getEnvValue("ALGOLIA_INDEX_NAME") || algoliaPublicConfig.indexName;
const siteSearch: DefaultTheme.Config["search"] =
algoliaAppId && algoliaSearchApiKey && algoliaIndexName
? {
provider: "algolia",
options: {
appId: algoliaAppId,
apiKey: algoliaSearchApiKey,
indexName: algoliaIndexName,
},
}
: {
provider: "local",
};
export default defineConfig({
themeConfig: {
search: siteSearch,
},
});这些参数的安全边界如下:
| 参数 | 来源 | 是否可以写前端代码 |
|---|---|---|
appId | Algolia Application ID | 可以 |
searchApiKey | Search-Only API Key | 可以 |
indexName | Index Name | 可以 |
siteVerification | Meta tag 验证码 | 可以 |
Admin API Key | Algolia Admin API Key | 不可以 |
Search-Only API Key 的设计目标就是给前端搜索读取索引用。它会出现在浏览器里,不属于服务端密钥。真正只能放在 Algolia Crawler 后台的是 Admin API Key。
如果想保留中文搜索框文案,可以在 Algolia 分支的 options 中补充 locales:
export default defineConfig({
themeConfig: {
search: {
provider: "algolia",
options: {
appId: "B2S5VC6T26",
apiKey: "7842783a4e6cb13827082894378549d3",
indexName: "jerry-up-blog",
locales: {
root: {
placeholder: "搜索文档",
translations: {
button: {
buttonText: "搜索",
buttonAriaLabel: "搜索",
},
modal: {
searchBox: {
resetButtonTitle: "清除查询",
resetButtonAriaLabel: "清除查询",
cancelButtonText: "取消",
cancelButtonAriaLabel: "取消",
},
startScreen: {
recentSearchesTitle: "最近搜索",
noRecentSearchesText: "暂无最近搜索",
saveRecentSearchButtonTitle: "保存到最近搜索",
removeRecentSearchButtonTitle: "从最近搜索中移除",
favoriteSearchesTitle: "收藏",
removeFavoriteSearchButtonTitle: "从收藏中移除",
},
errorScreen: {
titleText: "无法获取结果",
helpText: "请检查网络连接后重试。",
},
noResultsScreen: {
noResultsText: "没有找到相关内容",
suggestedQueryText: "可以换个关键词试试",
},
footer: {
selectText: "选择",
navigateText: "切换",
closeText: "关闭",
searchByText: "搜索由",
},
},
},
},
},
},
},
},
});第一次集成先使用最小配置跑通搜索。确认能搜索到文章后,再补充中文文案、搜索策略和 Ask AI 等增强配置。
2.5.4. 部署和验证
统一确认构建命令和输出目录。
textBuild command: pnpm run build Output directory: dist本地手动打包时,才需要先安装依赖:
shpnpm install && pnpm run build统一确认 Algolia 公共参数。
优先写进配置常量Application ID、Search-Only API Key、Index Name和Site Verification都会出现在前端页面或请求中,可以直接写进.vitepress/config.mts。构建环境变量只作为覆盖手段,不是必填项。textappId=B2S5VC6T26 searchApiKey=7842783a4e6cb13827082894378549d3 indexName=jerry-up-blog siteVerification=ALGOLIA_SITE_VERIFICATION_CODE如果不想把公共参数写进代码,也可以在部署平台使用环境变量覆盖:
textALGOLIA_APP_ID=B2S5VC6T26 ALGOLIA_SEARCH_API_KEY=7842783a4e6cb13827082894378549d3 ALGOLIA_INDEX_NAME=jerry-up-blog ALGOLIA_SITE_VERIFICATION=ALGOLIA_SITE_VERIFICATION_CODE场景 推荐做法 固定个人博客配置 写进 .vitepress/config.mts的algoliaPublicConfig临时切换索引或验证码 使用构建环境变量覆盖 Crawler 写入索引 只在 Algolia Crawler 后台使用 Admin API Key在 Algolia Crawler 后台手动运行一次抓取。
打开线上博客,点击右上角搜索框,输入文章标题或正文关键词。
截图槽位:搜索效果这里后续补充 VitePress 搜索弹窗、命中标题和命中正文的截图。
如果搜索无结果,按下面顺序排查:
现象 优先检查 搜索弹窗打不开 provider、appId、apiKey、indexName是否写对弹窗打开但无结果 Crawler 是否运行成功,Index records 是否大于 0 只搜到导航或页脚 recordExtractor是否移除了侧边栏、导航、页脚新文章搜不到 是否重新部署,Crawler 是否重新抓取 本地能打开线上不行 域名、HTTPS、访问限制、CORS 或网络环境
完成后,Algolia 的集成关系就是:
VitePress 页面 -> 公开部署地址 -> Algolia Crawler -> Algolia Index -> VitePress 搜索框3. 部署
3.1. Cloudflare
Cloudflare Pages 适合托管静态站点,支持 Git 仓库自动构建,也支持手动上传构建产物。
登录 Cloudflare,进入 Workers 和 Pages 概述页,创建应用程序。

选择构建源。Cloudflare Pages 支持 GitHub、GitLab,也支持手动上传资产。
上传限制手动上传资产有大小限制。如果构建产物较大,建议将代码推送到 GitHub 或 GitLab 后,通过 Git 集成完成部署。

选择存储库,设置构建和部署配置。
textBuild command: pnpm run build Build output directory: distAlgolia 公共参数按
2.5.4. 部署和验证的统一清单写进配置常量;只有需要覆盖时才配置环境变量。构建平台会自动安装依赖,所以这里的Build command不需要写pnpm install && pnpm run build。如果是手动本地打包,再使用下面第 5 步的命令。

设置部署分支、自动部署策略和部署目录。

本地打包,并将
dist文件夹下的内容推送至 GitHub 仓库。shpnpm install && pnpm run build
如果未开启自动部署,需要手动点击重试部署。

部署完成后,打开访问地址确认站点可用。

3.2. Netlify
Netlify 节点和访问链路可能受网络环境影响,国内访问稳定性需要按实际情况验证。
登录 Netlify 进行 Sites 配置。Netlify 支持 GitHub、GitLab、Bitbucket、DevOps 等平台。

选择项目,配置部署。
textBuild command: pnpm run build Publish directory: distAlgolia 公共参数按
2.5.4. 部署和验证的统一清单写进配置常量;只有需要覆盖时才配置环境变量。Netlify 会在构建流程中自动安装依赖,Build command保持pnpm run build即可。
修改域名,根据实际需要是否开启推送自动部署。

3.3. Gitee Pages
2024 年 5 月曾出现无法访问、无法部署的情况。
目前 Gitee Pages 支持 Jekyll、Hugo、Hexo 编译静态资源。使用 VitePress 等其他静态网站生成器时,通常需要先在本地打包,再上传静态资源到仓库。
登录 Gitee,进行实名认证。

新建项目,并开通 Gitee Pages。

设置
/src/.vitepress/config.mts的base选项与仓库名保持一致。
设置部署分支以及部署目录。

本地打包,并将
dist文件夹推送至仓库。shpnpm install && pnpm run build
点击更新。

部署完成后,打开访问地址确认站点可用。
