Skip to content

个人博客自建指南(7.2 番外):草稿与私密文章 —— 构建但不公开

前言

第7篇我们实现了 git push 直达线上,从此写文章、部署一气呵成。7.1番外我们配置了基础的SEO,但随之而来一个问题:有些文章写了一半、有些是测试笔记、有些暂时不想公开——它们也在 docs/ 目录下,也会被构建、被放进 sitemap.xml、被搜索引擎发现。

当前需要的是:构建存在,自己能看,但搜索引擎和访客都找不到入口。

这篇就来解决这个问题。做完之后,你的站点将拥有一个“只有你知道”的私人区域。

一、方案选择

方案优点缺点推荐度
直接不放 docs/最干净本地预览不方便,还得切目录
只不加导航/侧边栏简单sitemap 仍会暴露,搜索引擎仍可能收录
noindex + sitemap 过滤 + robots 禁止三层保险,自己可访问需一次性配置推荐

搜索引擎优化是让该被看到的被看到,而这篇是做相反的事:让不该被看到的,不被看到。

1.1 架构总览

本地写 md(放在 docs/other/ 下)
  → pnpm build 构建时:
      ① sitemap 用 transformItems 过滤 /other/ 目录
      ② 自动给 /other/ 页面注入 noindex 标签
      ③ robots.txt 禁止抓取 /other/
  → 部署到 ECS
    → 搜索引擎:看不到,不收录
    → 访客:没有链接可以点进来
    → 你自己:直接输入 URL 即可访问

全程不涉及密码验证、不涉及 .htaccess、不涉及后端鉴权。纯粹靠搜索引擎协议和站点配置来实现“隐藏”。

1.2 前置条件

  • 已完成第7、7.1篇的全部步骤(自动化部署已就绪,SEO基础配置已完成)
  • 你的草稿/私密文章位于 docs/other/ 目录下(或其他你指定的目录)
  • 这些文章已有基本的 frontmatter

二、sitemap 过滤私密目录

搜索引擎发现新页面的主要途径之一就是 sitemap。如果私密文章出现在 sitemap.xml 里,就等于主动把入口告诉了搜索引擎。

.vitepress/config.ts 中找到 sitemap 配置,加上 transformItems 钩子:

typescript
sitemap: {
  hostname: 'https://jiejinx.cn',

  transformItems: (items) => {
    // 过滤掉 /other/ 下的私密页面
    return items.filter(i => !i.url.includes('/other/'))
  },
},

transformItems 是 VitePress 官方提供的钩子,在生成 sitemap.xml 之前执行。它接收所有待输出的条目,返回的数组就是最终写入文件的条目。这里用 filter 把 URL 中包含 /other/ 的条目剔除。

执行 pnpm build 后,检查生成的 sitemap.xml:

bash
grep "other" docs/.vitepress/dist/sitemap.xml

如果没有输出,说明过滤成功。

三、自动注入 noindex 标签

sitemap 过滤了,但如果搜索引擎通过其他途径(比如外部链接、书签导入、直接猜测 URL)访问到这些页面,它仍然可能被收录。需要在页面级别告诉搜索引擎:不要索引我。

VitePress 提供了一个钩子 transformHead,可以在构建时根据页面路径动态修改 <head> 标签。在 .vitepress/config.ts 中添加:

typescript
export default defineConfig({
  // ... 其他配置

  transformHead({ pageData }) {
    // 如果页面路径以 other/ 开头,注入 noindex
    if (pageData.relativePath.startsWith("other/")) {
      return [["meta", { name: "robots", content: "noindex, nofollow" }]];
    }
  },
});

pageData.relativePath 是相对于 docs/ 目录的文件路径,比如 other/other1.md。只要它以 other/ 开头,就自动注入 <meta name="robots" content="noindex, nofollow">

部署后,打开 https://jiejinx.cn/other/other1,查看页面源代码,确认 <head> 中包含:

html
<meta name="robots" content="noindex, nofollow" />

若页面无法正常加载出来,可能是nginx配置中的try_files没有设置html后缀导致,ECS上执行以下命令:

bash
# 更新配置
sudo sed -i 's|try_files $uri $uri/ /index.html;|try_files $uri $uri.html $uri/ /index.html;|' /etc/nginx/conf.d/jiejinx.cn.conf

#重启nginx
sudo nginx -t && sudo systemctl reload nginx

刷新线上页面查看页面head内容。

四、robots.txt 禁止抓取

即使 sitemap 过滤了、页面加了 noindex ,爬虫仍然可能通过其他链接发现这些页面并尝试抓取。robots.txt 是最后一道防线:直接告诉爬虫,这个目录不要进来。

编辑 docs/public/robots.txt

txt
User-agent: *
Allow: /

Disallow: /other/

Sitemap: https://jiejinx.cn/sitemap.xml

部署后访问 https://jiejinx.cn/robots.txt,确认内容正确。

五、不在导航和侧边栏出现

这是最基础的一步。检查你的 navsidebar 配置,确保没有指向 /other/ 的链接。

如果你之前为了自己方便加过,现在删掉。如果你需要快速访问私密文章,建议用浏览器书签,而不是在站点上留入口。

六、不让草稿被搜索到

第五步解决了导航和侧边栏的入口问题,但还有一个隐蔽的漏洞:VitePress 的本地搜索

如果你启用了 provider: 'local' 的搜索功能,它默认会把所有被构建进 dist/ 的页面都编入索引——包括你放在 docs/other/ 下的草稿。这意味着,即使导航栏和侧边栏没有入口,读者仍然可以通过搜索框搜到草稿内容。

有两种处理方式,按你的需求选一种即可。

1. 按文件单独屏蔽(轻量,适合偶尔写草稿)

在每个草稿文件的 frontmatter 中加一行:

markdown
---
search: false
---

这样 VitePress 本地搜索会跳过该页,不建立索引。

优点:按文件控制,粒度细。
缺点:每篇草稿都得记得加,忘了就漏网。

2. 按路径批量屏蔽(治本,推荐)

docs/.vitepress/config.tssearch.options 中加 _render 函数,按路由路径过滤:

typescript
search: {
  provider: 'local',
  options: {
    // 搜索页面渲染过滤指定路径下的页面
    _render(src, env, md) {
      // 如果路径以 /other/ 开头,返回空字符串跳过索引
      if (env.relativePath.startsWith('other/')) {
        return ''
      }
      // 正常渲染
      return md.render(src, env)
    },
    //locales...中文配置
  }
}

path 是相对于 docs/ 的路由路径,以 / 开头。

优点:配置一次,整个目录下的草稿永久不进搜索。
优点:新增草稿无需额外操作,自动屏蔽。

3. 构建期就让草稿不参与(最干净)

如果你希望草稿文件连 dist/ 都不进(线上完全不存在),可以在 config.ts 顶层加 srcExclude

typescript
export default defineConfig({
  // 草稿不参与构建
  srcExclude: ['other/**/*.md'],   
  themeConfig: {
    search: { provider: 'local' }
  }
})

这样 pnpm run build 时草稿文件直接被忽略,dist 里没有对应 HTML,本地搜索自然也搜不到。

缺点:本地 dev 预览草稿时需要临时注释掉这行配置,略麻烦。

七、完整配置一览

把以上所有配置汇总到 .vitepress/config.ts 中:

typescript
// docs/.vitepress/config.ts

import { defineConfig } from "vitepress";

export default defineConfig({
  title: "阶进遐的技术随笔",
  description: "阶进遐(jiejinx.cn)的个人技术博客",
  lang: "zh-CN",

  // 站点地图
  sitemap: {
    hostname: "https://jiejinx.cn",
    transformItems: (items) => {
      // 过滤掉 other/ 下的私密页面
      return items.filter((i) => !i.url.includes("other/"));
    },
  },

  // 动态注入 noindex
  transformHead({ pageData }) {
    if (pageData.relativePath.startsWith("other/")) {
      return [["meta", { name: "robots", content: "noindex, nofollow" }]];
    }
  },

  

  // 主题配置
  themeConfig: {
    // ... 你的 nav、sidebar 等配置
    search: {
      provider: 'local',
      options: {
        // 草稿目录的路由前缀过滤
        _render(src, env, md) {
          // 如果路径以 /other/ 开头,返回空字符串跳过索引
          if (env.relativePath.startsWith('other/')) {
            return ''
          }
          // 正常渲染
          return md.render(src, env)
        },
        //locales...中文配置
      }
    }
  },
});

robots.txt文件配置(docs/public/robots.txt):

txt
User-agent: *
Allow: /

Disallow: /other/

Sitemap: https://jiejinx.cn/sitemap.xml

八、验证清单

部署后逐一检查:

检查项方法预期结果
sitemap 已过滤https://jiejinx.cn/sitemap.xml没有 /other/ 开头的 URL
noindex 已注入查看 /other/other1 页面源码<meta name="robots" content="noindex, nofollow">
robots.txt 正确https://jiejinx.cn/robots.txt包含 Disallow: /other/
站内搜索用草稿文章内的关键词搜索没有草稿文章的搜索结果出现
无公开链接浏览全站,检查所有页面没有指向 /other/ 的链接
自己可访问直接输入 URL页面正常显示

九、日常维护

新增私密文章

直接把 .md 文件放到 docs/other/ 目录下,不需要修改任何配置。transformItemstransformHead 是基于路径模式匹配的,会自动覆盖新文件。

将私密文章转为公开

把文件从 docs/other/ 移动到公开目录(如 docs/self-host/),然后在 navsidebar 中添加链接。sitemap 会自动包含它,noindex 也不会再注入。

查看所有私密文章列表

如果你想知道自己有哪些私密文章,可以直接在本地文件管理器中查看 docs/other/ 目录,或者在 VSCode 中浏览。不需要在站点上建索引页。

十、故障排查

1. sitemap 中仍有 /other/ 页面

检查 transformItems 中的过滤条件。i.url 是完整的 URL 字符串(如 https://jiejinx.cn/other/other1),确认你的条件 includes('/other/') 能匹配到。

2. noindex 没有生效

检查 transformHead 中的路径判断条件。pageData.relativePath 的值是相对于 docs/ 的路径,不包含前导斜杠。确认你的文件路径确实以 other/ 开头。

3. 自己忘了 URL 怎么办

私密文章的 URL 由 文件名 决定。如果你docs/other/ 目录下有 16 篇 other 文章,文件名依次为,

`other1.md`
`other1.md`
...
`other16.md`

那么,文件对应的URL 分别是:

https://jiejinx.cn/other/other1
https://jiejinx.cn/other/other2
...
https://jiejinx.cn/other/other16

建议在本地维护一个私密 URL 列表,或者直接记住命名规则。

十一、总结

这篇我们实现了:

需求做法
搜索引擎不收录noindex + sitemap 过滤 + robots 禁止抓取
访客找不到入口不在导航/侧边栏出现,不在任何页面生成链接,站内无法搜索出结果
自己能访问直接输入 URL,页面正常渲染
新增私密文章直接放文件,无需改配置
转为公开移动文件 + 加导航链接

从此你的站点拥有了两层空间:

  • 公开层:导航可见、sitemap 包含、搜索引擎可收录
  • 私密层:构建存在、自己可看、搜索引擎和访客都找不到

结合第7篇的自动化部署,你的博客工作流现在是这样的:

公开文章:写 md → git push → 自动部署 → 搜索引擎收录
私密文章:写 md → git push → 自动部署 → 只有自己知道

两层互不干扰,一条流水线打通。