本站是怎么搭起来的:零依赖、可离线、一个文件加一篇文章

这个站是我用来记笔记的地方,主题是网站搭建、服务器和域名。既然主题就是「建站」,那它本身也该是能被看懂、能被改的一个样例,而不是套个主题生成器就完事。

选型:为什么不用 Hexo / Hugo / VitePress

它们都很好,但对「随手记一篇」这件事来说,引入构建链是有代价的:

  • 要装 Node、装依赖、等编译,node_modules 动辄几百 MB;
  • 换台电脑想改一句话,得先把环境搭回来;
  • 主题一旦深度定制,升级就等于重写;
  • 几年后依赖跑不起来,站就「坏」了——而纯静态 HTML 十年后照样能打开。

所以我用了最土也最稳的方案:原生 HTML + CSS + JS,零依赖,零构建

目录结构

bash
baize-network/
├── index.html              # 唯一页面,所有视图在这里切换
├── assets/
│   ├── css/style.css       # 全部样式:主题变量 / 布局 / 响应式
│   └── js/
│       ├── markdown.js     # 极简 Markdown 解析 + 代码高亮(约 300 行)
│       ├── posts.js        # 全站配置 + 文章数据
│       └── app.js          # 路由、渲染、搜索、目录、主题切换
└── README.md

三个文件各干一件事

  1. markdown.js —— 只支持写笔记真正会用到的语法:标题、列表、表格、引用、围栏代码块、行内代码、链接、图片。先转义再解析,不会渲染出危险的 HTML。代码高亮用逐字符扫描 + 规则匹配实现,比引一个 highlight.js(约 100KB)划算得多。
  2. posts.js —— 配置加数据。文章正文是 Markdown,用字符串数组 .join() 拼起来,这样反引号不用转义,写起来和 .md 文件几乎一样。
  3. app.js —— hash 路由、渲染列表与正文,顺带做搜索、目录高亮、代码复制、阅读进度条、深浅色主题。

路由为什么用 hash

因为要支持 file:// 直接打开。传统路径路由(/post/1)需要服务端把请求回退到 index.html,双击本地文件时会直接 404;hash 路由把状态放在 # 后面,不触发请求,本地和服务器都能跑。

代价有两个:URL 里多了个 #;服务端拿不到 hash(SEO 与服务端统计会受影响)。对纯个人笔记来说,这个交换是划算的。

页面与路由对照

路由视图说明
#/首页Hero + 分类筛选 + 卡片网格
#/category/服务器分类页该分类下的全部文章
#/tag/Nginx标签页该标签下的全部文章
#/archive归档页按年份倒序的时间线
#/search/关键词搜索页标题/摘要/标签/正文全匹配
#/post/:id文章页正文 + 右侧目录 + 上下篇
#/about关于页站点信息与技术栈

怎么新增一篇文章

posts.jsPOSTS 数组前加一个对象:

js
{
  id: "my-new-post",
  title: "标题",
  category: "服务器",
  tags: ["Nginx"],
  date: "2026-09-17",
  summary: "首页卡片上的一句话",
  content: ["## 小标题", "", "正文"].join("\n")
}

保存刷新即可,首页、分类、标签、搜索、归档、上下篇会自动包含它,不需要重新构建任何东西

本地预览

bash
cd baize-network
python3 -m http.server 8000
# 打开 http://localhost:8000

直接双击 index.html 也可以,功能完全一致。

后来陆续补上的

  • RSS 输出:node tools/build-feeds.js 生成 feed.xml / sitemap.xml / robots.txt
  • 搜索结果里高亮命中关键词
  • 文章底部推荐相关笔记(同分类 +3 分、同标签 +2 分)
  • 返回顶部按钮,以及按 / 直接聚焦搜索框

接下来想做的

  • 全文搜索加权(标题 > 标签 > 正文)
  • 把 Markdown 抽成独立 .md 文件,保留在线加载与本地内联两种模式

站点本身也是笔记的一部分:哪天我想换个写法,直接改就是了,反正一共就三个文件。