news 2026/10/21 16:19:17

我的第三个网站:用静态化实现低维护的个人站点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
我的第三个网站:用静态化实现低维护的个人站点

1. 在动手前,先想清楚这个“第三个”到底要解决什么问题

标题写的是“我的第三个网站”,听起来就是一次普通的重新建站,但只有亲手做过两轮、又陆续放弃过两个网站的人,才会明白“第三个”这三个字的分量。它不是数量上的累加,而是一次非常明确的转折:前两个网站教会了我“能上线”和“能长期用下去”是两件事。

我这次做的是自己的个人网站,定位很朴素:一个放技术笔记、项目作品和个人介绍的地方。没有在线商城,没有用户系统,不搞复杂后台。如果只追求“炫”,第三个网站根本没必要做;我要的是一个能安安静静跑很多年、更新起来不痛苦、成本极低的站点。如果你也正准备做自己的网站、作品集,或者想把手里的内容从某个碎片平台搬到自己的域名下,这篇文章应该能帮你少踩几个我踩过的坑。

1.1 前两个网站留下的教训

我的第一个网站,是大二还是大三那会儿做的个人主页。说是网站,其实就是一堆手写的 HTML 页面,CSS 全靠复制粘贴,图片东一张西一张堆在文件夹里。当时觉得能打开就是胜利,但没过多久就发现问题了:想改一个导航栏的文字,得打开十几个文件挨个改;想把“作品”从两行变成三行,样式全乱。最后我干脆把整个目录删掉重做。这个阶段最大的教训是:网站的生命力不在页面漂亮不漂亮,而在内容更新和结构调整是不是方便。

第二个网站就“正规”多了。我上了动态博客系统,配了数据库、在线后台,能直接在网页里打字发布文章,还能装插件。刚开始确实爽,后台登录、写文章、传图片,一切都像那么回事。可后来维护成本慢慢变得让人烦躁:动态程序每隔一阵就提示更新,数据库偶尔连接失败,插件之间还会冲突;更烦的是各种扫描程序天天来问候后台登录页,垃圾评论多到需要专门挂过滤插件。我陷入了“不停修东西”而不是“持续写东西”的循环。一个内容网站,把作者的时间和热情全耗在处理系统问题上,这方向从一开始就不对。

1.2 定边界:第三站不是“什么都有”

所以到第三个网站,我做的第一件事不是选技术,而是先列需求,并且大胆地做减法。我把能想到的功能全部写出来,然后自己给自己打分:没有它,我还能好好更新吗?不能去掉的才算核心功能。

需求优先级我的最终方案
发布文章P0本地写 Markdown,构建后发布
展示作品P0用结构化 Markdown 数据生成项目页
个人简介P1单独一个静态页面
评论互动P2邮件联系方式 + 外部评论区
在线聊天P3不做
后台管理P3不做
会员系统P3不做

把 P3 的需求一个个划掉之后,整站其实就剩三类东西:文章、作品、关于我。这个边界非常重要,因为后续所有的技术选型都基于这个边界展开。没有用户系统,就不需要考虑登录态;没有在线评论,就不需要维护实时数据库;没有后台,就少了一大块安全漏洞面。做个人网站,功能少不是缺憾,反而是能长期运行的前提。

注意:这里的“不做评论”“不做后台”不是绝对标准。如果你的网站确实需要用户投稿、实时聊天这类功能,那静态方案就不合适。边界要跟着你的实际用途走,而不是跟着别人的推荐走。

2. 技术选型:为什么这次的组合更像“减法”

很多人做网站,习惯先听别人说最近哪个框架火、哪个工具流行,然后一头扎进去。我在第三个网站上正好反过来:先问自己“这个需求需要多复杂”,再选尽可能简单的方案。最后定下来的是静态站点生成器 + 对象存储 + CDN,整套链路里没有一个常年运行的应用服务器,也没有数据库。你可能觉得这不够“技术”,但对内容型个人网站来说,这恰恰是最稳的组合。

2.1 静态化是个人网站的主流答案

动态网站和静态网站的核心区别,可以理解成一个是“现炒现卖”,一个是“预制菜”。动态方案是用户每次访问,服务器都要去数据库里取数据、渲染模板、生成页面再返回;静态方案是在构建阶段就把所有 HTML 页面生成好,用户访问时直接把现成的文件扔给浏览器。对内容更新频率不高、以阅读为主的个人网站来说,“预制菜”效率高太多了。

我拿前两个网站做对比,印象特别明显:

对比维度动态方案静态方案
访问速度依赖服务器性能、数据库查询速度文件直接由 CDN 边缘节点返回
安全暴露后台、插件、运行环境,攻击面大没有运行时、没有后台,攻击面很小
维护要更新程序、备份数据库、清垃圾评论内容就是文件,构建发布后即可
扩展能力适合实时交互、强功能应用适合内容展示、作品集、文档站

当然,静态化也不是万能的。如果页面需要根据每个用户显示不同内容,比如“你好,某某”,或者要做即时聊天、表单提交后的实时反馈,那么纯静态方案就非常吃力。这也是我一开始强调边界的原因:技术选型不是找最强的,而是找一个刚好覆盖你需求、长期维护成本最低的。

2.2 内容层:用 Markdown 文件替代数据库

第二个网站让我最难受的,是内容被锁在数据库里。想备份要导出,想迁移要转换,甚至想用脚本批量修改某个错别字都费劲。第三个网站我彻底换了个思路:所有文章和作品信息都用 Markdown 文件保存,数据库直接退场。

每篇文章其实就是一个带“头部信息”的文本文件:

--- title: "我的第三个网站终于上线了" date: 2024-06-12 tags: [个人网站, 静态化, 部署] summary: "从动态博客转向静态化个人网站的过程记录" draft: false --- 这里是文章正文,用纯文本写就行。

文件放在项目文件夹里,天然就是文本,可以被版本管理系统追踪。内容改动在不在,谁改过,什么时候改的,全都有记录。最舒服的是写文章不再依赖那个动不动就弹更新的在线后台,我可以在任何顺手的文本编辑器里写,写完存盘提交就完事。文本文件比数据库后台更透明、更好迁移,想换一个静态站点生成器也几乎无成本,把 Markdown 文件和目录结构保留好就行。

2.3 部署层:对象存储加 CDN 的组合

前两个网站要么直接租虚拟主机,要么买云服务器自己搭环境。第三个网站我选择把生成的静态文件传到对象存储,再用 CDN 做分发。简单说,对象存储就是一个可以放文件、可以让大家访问的“网盘”,CDN 则在世界各地都有缓存节点,用户就近拉取文件。

这套方案有几个实打实的好处:

  • 不需要维护操作系统,不存在“忘了打补丁”的问题。
  • 没有 24 小时必须开着的应用服务器,成本低到可以忽略。
  • 文件分发有 CDN 兜底,访问量和带宽压力被边缘节点挡掉。

我自己的实践感受是,维护成本几乎降到了零。以前登录后台第一反应是“有没有更新要处理”,现在打开管理界面只会看见“这个月有几个新访问来源”这类数据。做个人网站最需要的不是掌控感,而是把系统层面的麻烦全部外包,留出时间写内容、打磨页面。

提醒:静态文件放对象存储后,一定要把“公开读”权限配好,但不要把整个存储桶的“写权限”暴露出去。平时发布走自动化工具,不要手动去管理后台上传,减少误操作。

3. 核心实现:从空白目录到一个能上线的站点

技术选型定完,剩下的就是具体把网站“长”出来。我给第三个网站定的目录结构并不复杂,重点在于让内容、模板、脚本、资源各归其位。

3.1 内容目录怎么组织

用文字描述不如直接看目录树:

my-site/ ├── content/ │ ├── posts/ # 文章,每篇一个 Markdown 文件 │ │ ├── hello-world.md │ │ ├── project-lessons.md │ │ └── ... │ └── projects/ # 作品集,每个项目一个 Markdown 文件 │ ├── tool-a.md │ └── tool-b.md ├── assets/ │ ├── images/ # 文章和页面用到的原始图片 │ └── css/ ├── templates/ # 页面模板,用来把 Markdown 渲染成 HTML │ ├── home.html │ ├── post.html │ └── project.html ├── scripts/ │ └── build.py # 构建脚本 ├── public/ # 构建结果,最终上传的目录 └── config.toml # 站点全局配置

文章放content/posts,作品放content/projects,模板单独放templates,构建结果统一生成到public。这个结构最大的好处是“约定大于配置”:新文章只要按命名规则丢到对应文件夹,重新构建就能自动出现在列表页里。不需要去某个管理后台填写分类、设置别名,一切都跟着文件夹和文件头部信息走。

3.2 页面生成逻辑和数据模型

第三个网站的页面生成逻辑,本质上是一个非常简单的模板引擎练习:读取 Markdown 文件,解析头部信息,把正文转成 HTML,然后套进模板。我在构建脚本里写了一个核心函数,思路大致是这样:

def build_post(src_path, templates): # 1. 读取 Markdown 文件并解析 front matter meta, content = parse_markdown(src_path) # 2. 把正文转成 HTML body_html = markdown_to_html(content) # 3. 选择文章模板并填充数据 html = templates["post.html"].render( title=meta["title"], date=meta["date"], tags=meta["tags"], content=body_html, ) # 4. 按文章 slug 生成目录,写出 index.html out_dir = Path("public") / meta["slug"] out_dir.mkdir(parents=True, exist_ok=True) (out_dir / "index.html").write_text(html, encoding="utf-8")

数据模型也很简单:一篇文章拥有标题、日期、标签、摘要、链接别名(slug)、正文这几个字段。列表页和标签页的排序逻辑,无非是把所有文章按日期倒序排,再按标签分组。作品页则多了“项目状态”“技术栈”“链接地址”这几个字段,本质上和文章模型差不多。

这个阶段给我最大的启发是:绝大多数个人网站,并不需要一个庞大的后台框架。一个遍历文件夹、读文件、渲染模板的脚本,几十行代码就能做到。真正花时间的反而是组织好这些数据,让页面风格统一、浏览逻辑顺畅。

3.3 三处不能忽略的细节:图片、缓存、链接

页面能生成,只是万里长征第一步。有三个细节我在第三站里单独做了处理,它们是决定网站“用起来香不香”的关键。

第一是图片。以前我习惯直接把原图丢进去,一张照片动不动两三兆,打开文章像在加载一个相册。这次我在构建流程里加了一步图片处理:上传前先压缩,统一转成适合网页展示的格式,并按需生成不同尺寸。同一张图,移动端加载小图,桌面端加载大图,不再让访客的流量白白浪费。

第二是缓存策略。静态站点的文件几乎不变,特别适合长时间缓存。我在 CDN 层对带文件指纹的资源设置了很长的缓存时间,比如 CSS、JS、压缩图这些文件名带了哈希值的资源,缓存一年都没问题;而 HTML 页面缓存时间设置得短一些,方便内容更新后尽快生效。这样做之后,页面重复访问速度快了很多,回源压力也几乎为零。

第三是链接结构。个人网站最怕文章改个链接别名,旧地址全变成 404。我从一开始就规定好每篇文章的 slug,一锤定音,轻易不改。如果实在要改,就在构建时生成一份旧地址到新地址的重定向关系。顺便用脚本检查站内所有内部链接,确保没有死链。

3.4 评论、统计和搜索的轻量替代

需要交互怎么办?我给第三站选的是“轻量替代”。评论没有在站内直接做,而是在每篇文章底部放了“发送邮件讨论”的入口,同时接了一个外部评论区,用户点击就能跳出去发言。这样既保留了互动可能,又不给自己增加内容审核和数据库维护的负担。

访问统计同样不依赖重脚本。我定期把 CDN 的访问日志拉回来,在本地简单分析一下来源、页面浏览量和热门内容。数据足够看出“哪篇文章值得继续写”,又不会为了加载一个统计脚本拖慢页面。搜索则更简单,构建时把所有文章标题、摘要、正文内容生成一份 JSON 索引,页面上用一个小的搜索框做前端检索,实时返回结果。没有后端接口,也不需要付费搜索服务,这对个人站已经绰绰有余。

4. 从本机到线上:我把发布做成了“一键”

网站做到这一步,内容模型和页面模板都清晰了,最后真正让第三个网站“活”起来的是发布流程。我不想再像第二个网站那样,每次更新都打开后台,一边写一边担心保存失败。我想要的工作流是:本地写、保存、提交,然后网站自动更新。

4.1 本地工作流的几个常用命令

我特意把所有频繁用到的操作封装成了简单命令,给自己减少记忆负担:

make serve # 本地预览,改文件后自动刷新浏览器 make check # 检查链接是否有效、文章头部信息是否完整 make build # 生成 public/ 目录 make deploy # 同步到对象存储并刷新 CDN 缓存

本地预览解决“写的时候能看见效果”,检查命令解决“别把带病内容发出去”,构建命令负责把 Markdown 变成最终文件,发布命令负责把最终文件推上云。平时更新一篇文章,我只需要写 Markdown,然后依次按下make build和make deploy,全程不过一分钟。如果哪天改了模板或新增了页面结构,也只需要在本地多预览几次确认样式没问题,再构建发布。

4.2 自动发布流水线:提交后就更新

后来我连手动执行都嫌麻烦,又加了一步自动化。核心思路是:主分支收到新提交后,自动完成从拉代码到刷新缓存的整个过程。流程写成伪代码大概是:

触发条件:代码托管平台收到主分支推送 1. 拉取最新源码 2. 安装构建工具依赖 3. 执行构建脚本,生成 public/ 4. 把 public/ 同步到对象存储 5. 调用 CDN 接口刷新资源缓存 6. 通知我发布成功或失败

这个流水线跑起来后,第三个网站才真正变成“只谈内容,不谈运维”的状态。我写了一篇文章,提交到主分支,剩下的地方平台和脚本自己跑完。偶尔构建失败,也只是因为某个模板写错了或者网络波动,查看日志定位起来都不难。

经验:把“发布”做成流水线,不只是为了省那几分钟,更是为了让过程可重复。手动上传最大的隐患是“这次和上次操作不完全一样”,某个文件漏传、缓存忘刷,问题都藏在细节里。自动化能把这种低级失误直接消灭。

4.3 域名、HTTPS 与访问加速

部署的最后一步,是把域名接入 CDN,并强制开启 HTTPS。我做了三件事:把 DNS 解析从原来的服务器地址改成 CDN 提供的加速地址;把 HTTP 请求统一 301 重定向到 HTTPS 主域名,避免出现“同一个页面有多个地址”的 SEO 问题;证书设置里开启自动续签,让浏览器小锁头永远不会过期。

对个人网站来说,HTTPS 现在已经不是可选加分项,而是底线。它直接影响浏览器地址栏的可信标识、表单数据安全,甚至影响搜索引擎对页面的评价。好在证书签发和续期早已自动化,我只需要在控制台里点一下开启,剩下的交给流程处理。

CDN 加速对国内外的访问速度提升也确实明显。以前第二个网站的服务器在某个机房,离得远的用户打开首页要转圈好几秒;现在静态文件从最近的节点返回,大部分地区都能做到“秒开”。做内容网站,速度本身就是阅读体验的一部分。

5. 上线以后:常见问题与排查经验

第三个网站上线后的第一个月,我没有急着写很多内容,而是有意识地观察它会不会出问题。这里把遇到过的和预判到的典型问题整理一下,给你做个速查。

5.1 改完文章,页面却不更新

这是静态站最经典的问题,十有八九是缓存。页面第一次被访问后,CDN 会把 HTML 缓存一段时间。即使我把文章重新构建、重新上传,缓存没过期时用户看到的还是旧版本。我的处理方法是:在脚本里,每次发布完主动刷新整站缓存;同时在本地预览后,用无痕窗口检查线上页面,确认显示的是新内容。

如果连主动刷新都还没生效,别急着怀疑平台,先看浏览器端是不是缓存了旧页面。检查 Network 面板里的响应头有没有“from disk cache”这类提示,有就说明是本地浏览器缓存,强制刷新或者等缓存过期就好。

5.2 链接失效和死链

内容多了之后,最容易出现两类链接问题。一类是我在文章里引用旧文章的地址,但旧文章后来改了 slug;另一类是图片路径写错,构建命令没发现,页面加载直接 404。我在检查脚本里加了一个“站内链接遍历器”,把 public 目录里生成的全部 HTML 扫一遍,找出指向不存在页面的链接,并逐条列出来。

这个检查一定要放进发布流程里,而不是想起来才跑一次。否则一旦形成死链,搜索引擎爬虫会不断抓到 404,对整站评价很不友好。

5.3 内容变多,构建速度变慢

大概写到几十篇文章时,我开始觉得每次构建要等的时间有点长。原因是每次构建都会重新扫描全部文章、重新压缩所有图片。解决办法有两个:一是把构建改成增量模式,只重新生成有改动的文章和受影响列表页;二是把原始图片从源码仓库里挪出去,单独放在对象存储上,不在构建时反复处理。

对于个人网站,构建时间从几秒变成几十秒也不是大问题,但提早意识到这个方向,可以避免内容多了之后再来动手术。

5.4 安全和垃圾流量

静态网站没有后台,最让动态网站头疼的暴力破解和后台扫描基本消失了。但完全零风险是不现实的,我依然做了几件小事:保证源码仓库不泄露,敏感配置通过环境变量注入而不是写死在仓库里;在 CDN 层开启一定程度的访问频率限制,防止某个 URL 被瞬间刷爆;robots.txt 里只开放应该被检索的路径,不开放任何临时目录。

对个人网站来说,“安全”的核心不是上多复杂的防护,而是别给自己留一个常年在线、没有及时升级的“活靶子”。静态化之后,靶子本身就不在了。

最后,我心里对“第三个网站”的一点新看法

如果你也在做“我的第三个网站”这类项目,我想说:真正让这个网站成功的,不是某个厉害的框架,也不是某个酷炫的特效,而是你愿不愿意半年后、一年后继续维护它、继续往里写东西。技术上的减法,换来的是内容上的加法;不需要半夜起来修数据库,才更愿意在周末坐下来写一篇长文。

我现在对这个网站最大的满意之处,是它已经不太需要“被维护”了。我打开后台的频率,远低于打开编辑器开始写新内容的频率。最后分享一个小技巧:刚开始别急着把所有功能都搭好,先把“从写文章到线上发布”这条最短路径跑顺。只要这条路径足够顺滑,后续的扩展都会很自然;如果这条路径很痛苦,前面做再多漂亮页面都留不住你。

第三个网站,对我而言终于不是建来玩的网站了,它是我真正愿意长期“住”下去的站点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 16:18:41

博图SCL+LAD混编:非标自动化设备控制程序框架实战解析

做非标自动化这些年,我越来越习惯在博图(TIA Portal)里用SCL和LAD混编的方式写程序。早年间我也迷信“一门语言打天下”,要么整个项目全LAD,要么全SCL,后来在某个配料站项目上被调试节奏逼得没办法&#xf…

作者头像 李华
网站建设 2026/10/21 16:17:37

SpringBoot + POI-TL:模板化生成Word报表的实战指南

如果你做过企业级项目,大概率被 Word 报表折磨过。一个月一张业务报表,模板改版一次,代码重写一次;格式稍微复杂点,原生 POI 写createParagraph、createTableCell能写到怀疑人生。后来我在某项目里接触到 POI-TL&#…

作者头像 李华
网站建设 2026/10/21 16:16:33

SVM分类入门实战:从玩具数据集到C与gamma调优

1. 从一个玩具数据集说起:为什么选择SVM做分类入门很多人学机器学习,第一个真正动手跑起来的分类器要么是逻辑回归,要么是KNN,SVM往往被排到后面。原因也简单——SVM听起来就"数学味"重,什么最大间隔、核函数…

作者头像 李华
网站建设 2026/10/21 16:16:32

C++ Primer Plus 第6版练习答案:从编译到避坑的完整指南

简介:这份资源是《C Primer Plus》第6版中文版编程练习答案的Word文档,面向正在学习C基础语法、需要对照练习结果自查的初学者与自学者。内容按章节组织,覆盖第二章「开始学习C」与第三章「处理数据」的多个练习,如姓名地址输出、…

作者头像 李华
网站建设 2026/10/21 16:16:14

构建可验证、可组合、可进化的个人技能操作系统

1. 项目概述:当“skills”不再只是简历上的单词,而成为可验证、可组合、可进化的个人能力操作系统“skills”这个词最近在技术社区、职业发展平台和高校教学研讨中高频出现,但它早已不是求职简历里那行潦草罗列的“Python/Photoshop/沟通能力…

作者头像 李华
网站建设 2026/10/21 16:16:04

硅二极管温度传感器:从PN结原理到工程选型全解析

前阵子调试某工业采集板,客户对温度测量这一路提出了"必须用数字传感器"的死要求。我算了一笔账:如果改用分立二极管测温方案,物料成本能压掉一大半,精度反而更好控。最后板子做出来,实测读数与标定用铂电阻…

作者头像 李华