☰
回归原生三件套:零依赖构建极简个人主页的实践
2026/10/29 9:05:29 网站建设 项目流程

1. 项目缘起:为什么我会用 "caveman" 命名一个网站项目

1.1 被框架包围之后,我想逃回"洞穴"

这个名为 caveman 的项目,源于我对自己工作流的一次彻底反思。过去几年,我日常接触的前端项目基本都是框架打底:启动项目先拉脚手架,装依赖要花几分钟,一个简单的展示页硬要拆出组件目录、路由配置、状态管理三件套。有一次我接到一个很小的活动落地页需求,预估原型半小时能写完,结果项目初始化、构建配置、依赖版本冲突、构建产物体积优化,折腾了大半天还没进入正题。那天晚上我坐在屏幕前突然意识到一件事:工具本应服务于表达,我却反过来被工具的时间成本绑架了。

于是我决定做一个"反潮流"的项目,名字就叫 caveman。这个名字有两层意思:一是字面上的“穴居人”,强调回归原始、只用最简单可靠的工具;二是提醒自己,当复杂度成为负担的时候,回到最直接的方式解决问题,往往比引入更多工具更有效。caveman 最终是一个完全基于原生 HTML、CSS、JavaScript 构建的个人主页项目,没有任何前端框架、没有构建工具链、没有包管理器依赖,所有文件都是可以直接双击打开的静态资源。

1.2 "穴居人建庇护所"式的前端理念

我给自己定了几条很"原始"的规矩。第一条,能用浏览器原生能力解决的,绝不引入第三方库;第二条,文件数量和代码行数不设限制,但依赖数量必须为零;第三条,整个项目必须能在五秒钟内完成预览,不需要等待依赖安装。这些约束听起来很极端,但它们其实是刻意为之的自我边界设定,就像穴居人只能在有限资源里建造能遮风挡雨的庇护所,这种限制反而能训练你专注于真正重要的事:内容结构、视觉呈现、加载性能。

caveman 要解决的问题非常具体:一个注重内容展示的个人主页,到底需要多复杂的技术系统?我观察了一圈同类站点,大部分内容的实际载体无非是几段文字、若干图片、一个作品集列表、一个联系方式。这些需求在二十年前的 Web 标准下就已经能做得很好,如今的浏览器原生能力只会更强。真正让这些页面变复杂的,其实是开发者自己引入的抽象层。caveman 试图证明一个观点:个人主页这类"信息展示型"站点,框架并不是必需品,甚至常常是负优化。

1.3 这个项目适合谁来参考

如果你属于以下几类人,这个项目的思路会很有参考价值。第一类是像我一样每天被工具链拖累的开发者,希望能从复杂度中抽身,找回用最朴素代码实现完整功能的掌控感;第二类是刚开始学习前端、还没选好"主攻方向"的新手,在没有框架干扰的情况下,先用原生三件套把 Web 基础打扎实,会是一个很健康的学习路径;第三类是独立开发者或小团队,运营官网、作品集、介绍页这类轻量场景时,与其扛着 React 或 Vue 的重型项目跑,不如用 caveman 这种方案轻装上阵。

当然,我必须同时说清楚:caveman 不是要否定框架。复杂业务系统、大型协作项目,框架的价值无可替代。我这里想探讨的是"合适"二字——给合适的场景选择合适的复杂度。caveman 给的就是一个"当复杂度不必要的时候,我们可以简单到什么程度"的完整样本。

2. 技术选型与方案设计拆解

2.1 原生三件套背后的选择逻辑

技术选型不能只看"哪个更先进",要先看"你要解决什么问题"。caveman 的目标是零依赖、秒开预览、长久可维护,在这个目标下面,原生 HTML、CSS、JavaScript 几乎是最优答案,而且它有一个框架方案永远比不上的优势:不依赖生态稳定性。

想象一下,你的个人网站是用某个框架写的,三年后框架版本大升级,脚手架变了,依赖包有安全漏洞需要更新,如果你想重新构建项目,光是处理兼容性问题就够烦的。但如果你的网站是一堆清晰的 HTML 文件和干净的 CSS、JS,十年后你打开它,依然能一眼看懂每一个标签和规则。我还额外算了一笔成本账:一个用 Vite 初始化的项目,node_modules 体积往往超过 200MB,而 caveman 整个站点压缩后不到 50KB。在存储、传输、维护三个维度上,原生方案的成本都接近于零。

2.2 信息架构:一个"洞穴"应该有哪些房间

抛开技术,caveman 首先是内容项目。我把个人主页规划成四个核心分区,也是"洞穴"里的四个房间。

  • 首页(入口):一句话介绍我是谁、我在做什么,以及最重要的——访问者能在这里获得什么。
  • 作品集(展览间):用清晰的卡片式列表展示我做过的代表性项目,每张卡片附带标题、简述、技术标签、成果链接。
  • 阅读笔记(书房):记录我最近在读和读完的书,重点写"这本书解决了我的什么问题",而不是复述目录。
  • 关于与联系(篝火区):更详细的背景、目前在做的事、常用的联系方式。

这种信息架构对应的是访问者的真实动线:先确认你是什么人,再看你做过什么,接着判断你的学习与思考方式,最后决定要不要和你产生联系。四个区块各司其职,不需要花哨的动效和复杂布局,内容的层级关系本身就足够引导用户了。

2.3 视觉设计约束:在限制里做减法

给 caveman 做视觉方案时,我给自己定的原则是"能用手写样式解决的问题,就不创造新的设计系统"。我没有引入任何 CSS 框架,而是自己维护了根级别的 CSS 自定义属性,用来管理颜色、间距、字体大小等设计令牌。这种做法和 Tailwind 这类工具在思想上有些相通,区别在于我只有几十行原生变量,完全透明、可自由改动。

配色上我选了一个很"土壤感"的暖色系:背景用接近岩壁的浅米色,文字用深棕色,强调色用赭石红。字体没有走系统字体栈的保守路线,而是引用了两个开源字体,一个用于正文,一个用于标题。整体视觉刻意保持朴素,让阅读成为核心体验,而不是让页面元素互相争抢注意力。响应式方面没有用任何复杂断点,内容设计了一个自然流动的单栏结构,在桌面端加了一个最大宽度约束和少量留白,移动端则完全单栏贯通,这种处理方式连一条媒体查询都不需要。

3. 核心功能与实操实现细节

3.1 页面骨架:怎么用语义化 HTML 打好地基

caveman 的每个页面我都坚持使用严格的语义化结构。以作品集页面为例,骨架大致是这样的:

<body> <header class="site-header"> <a href="/" class="brand">caveman</a> <nav aria-label="主导航"> <ul> <li><a href="/works.html" aria-current="page">作品集</a></li> <li><a href="/reading.html">阅读笔记</a></li> <li><a href="/about.html">关于我</a></li> </ul> </nav> </header> <main id="main"> <h1>做过的项目</h1> <p class="page-intro">这里记录的是我亲手从零到一完成的东西。</p> <ul class="work-list"> <li class="work-card"> <h2>某数据工具的设计与落地</h2> <p>一句话讲清楚项目解决的痛点与实现路径。</p> <p class="meta">技术栈:原生 JS · D3.js · IndexedDB</p> </li> <!-- 更多作品卡片 --> </ul> </main> <footer class="site-footer"> <p>© 2025 · 由原生三件套驱动</p> </footer> </body>

注意几个关键细节。第一个是导航使用了<nav>并加上aria-label,帮助屏幕阅读器用户识别这是主导航。第二个是当前页面的链接设置了aria-current="page",辅助技术可以明确告知用户当前位置。第三个是卡片列表没有用频繁出现的<div>,而是用<ul>搭配<li>承载项目条目,语义上更接近"一组并列内容"的本来含义。页面标题也不是随意安排的,<h1>明确表达当前页面主题,作品卡片里的项目名用<h2>作为次级标题,层级清晰可辨。

许多人觉得语义化 HTML 是"为了 SEO 喊口号",实际体验下来它对可访问性的帮助更直接。用屏幕阅读器逐页浏览后,你会明显感受到一个结构清晰的页面和一个全靠 div 堆出来的页面,在朗读顺序和理解成本上的差距有多大。这件事成本极低,收益却长期存在。

3.2 样式系统:CSS 变量驱动的轻量主题机制

caveman 的样式系统很克制,但绝不简陋。我在根选择器上定义了一套设计令牌,整个站点的视觉风格都从这里取用:

:root { --color-bg: #f5efe6; --color-surface: #fffaf1; --color-text: #3e2f22; --color-muted: #7a6a58; --color-accent: #a0522d; --space-base: 1rem; --space-md: 2rem; --space-lg: 4rem; --font-body: "Noto Serif SC", "Songti SC", serif; --font-display: "ZCOOL XiaoWei", "Noto Serif SC", serif; --max-width: 42rem; --radius: 12px; --shadow-soft: 0 4px 12px rgba(0, 0, 0, 0.06); }

定义完变量,我再写基础排版和组件样式时,几乎不用关心具体数值,只负责调用语义明确的变量名。比如正文段落的样式可以写成color: var(--color-text); line-height: 1.9;,卡片样式只需要background: var(--color-surface); box-shadow: var(--shadow-soft); border-radius: var(--radius);。

这样做最直接的好处是"改主题"变成了改几个变量。我试过把整个站点从暖色系切到冷色系,只改了根变量里五个颜色值,所有页面同步生效,时间不超过十分钟。这种效率是传统的"全局搜索替换颜色值"完全无法比拟的。间距系统我也全部围绕--space-base的倍数展开,比如padding: calc(var(--space-base) * 2),页面节奏因此非常统一,没有出现"这一块 12px、那一块 8px"的混乱感。

实现深色模式时,这套变量机制还能进一步发挥威力。我写了一个prefers-color-scheme: dark的媒体查询,在里面覆盖少数几个颜色变量,比如背景换成深褐色、文字换成浅沙色。由于组件样式全部引用变量,它们会自动适配新主题,代码量只有十几行。

3.3 原生 JavaScript 的"够用"原则

caveman 的交互需求集中在几个场景:移动端导航菜单的展开收起、作品卡片的长按提示、阅读笔记页的目录高亮。我全部用原生 JavaScript 实现,没有引入任何 DOM 操作库。这不代表我排斥 jQuery 或更现代的库,而是因为现代浏览器提供的querySelector、addEventListener、classList已经完全覆盖了这些简单操作。

举个例子,移动端导航的切换逻辑用原生 API 写出来非常清爽:

const navToggle = document.querySelector("#nav-toggle"); const navMenu = document.querySelector("#nav-menu"); navToggle.addEventListener("click", () => { const expanded = navToggle.getAttribute("aria-expanded") === "true"; navToggle.setAttribute("aria-expanded", String(!expanded)); navMenu.classList.toggle("is-open"); navToggle.textContent = expanded ? "打开菜单" : "关闭菜单"; });

这里我刻意处理了aria-expanded状态和按钮文字反馈,让键盘用户和屏幕阅读器用户都能感知菜单状态。原生写法让我对每一行代码的行为都了如指掌,出现问题时不需要往第三方源码里钻。性能方面,所有交互脚本加起来不到 3KB,浏览器解析执行完全无压力,页面交互响应速度几乎可以忽略加载时间。

3.4 不合理的"优雅"都不要:逐步增强策略

在几个交互相对复杂的页面上,我遵循了渐进增强原则。比如阅读笔记页的目录高亮功能,核心逻辑是用IntersectionObserver监听各个笔记章节的位置,当某个章节进入视口时,对应目录项高亮。这个功能在现代浏览器中运行得很流畅,但如果用户的浏览器不支持IntersectionObserver,脚本会自动跳过,页面静态目录依然完整可用。用户不会看到报错,只是少了高亮效果。

这种"缺了就降级"的理念是 caveman 项目的重要底色。页面先保证内容和基本功能完整体验,再叠加复杂的交互和样式。对于个人站点这种"内容为主"的场景,这个策略既保证了稳定性,又不会因为激进使用新技术而牺牲兼容性。

4. 部署发布与性能打磨记录

4.1 部署方案:静态站点的三种选择

caveman 构建后的产物是一整套纯静态文件,部署选项非常多。我从实际使用成本出发对比了三种方案。

  • 传统虚拟主机:老牌个人站长常用,支持 FTP/SFTP 上传,成本低,稳定性好,但配置 HTTPS 证书和伪静态比较折腾。
  • 对象存储静态网站托管:把文件传上去就能得到一个公网访问地址,带宽和流量单独计费,适合访问量不高的个人站点,成本通常很低。
  • 前端平台托管:很多平台支持自动构建部署,原生静态项目可以直接上传或者关联仓库之后自动发布,回滚和域名绑定都很方便,是我最后选择的方案。

我自己最后选择了对象存储加 CDN 的方式,因为 caveman 本身没有服务端逻辑,静态文件放在对象存储里是最贴合"原始"理念的路径。要更新的场景也简单:本地修改文件,上传替换,CDN 刷新缓存,整个过程三分钟之内搞定。

4.2 性能与资源体积控制

原生三件套并不意味着自动就快,该花的优化功夫一点不能少。我在性能打磨上做了几件事。

首先是图片处理。作品的封面图全部用工具压缩过,控制在 80KB 以内,格式统一选 WebP,配合loading="lazy"属性让首屏不加载屏幕之外的图片。其次是 CSS 和 JS 的交付方式,我没有额外做代码压缩和合并,因为原文件本来就不大,但特意避免了在 HTML 中内联大段脚本,这样可以借助浏览器缓存让脚本资源在页面切换时复用。第三是字体加载,中文字体文件体积不小,我只引用了标题字体的字重子集,并以font-display: swap和预加载的方式保证文字不会因为字体加载而不可见。

用浏览器开发者工具实测下来,整站首屏资源在 150KB 左右,在 4G 网络环境下的加载时间不到半秒,比许多装了一堆依赖的框架站点轻两个数量级。这个结果其实很正常,因为资源总量小,物理上就不存在"优化空间被框架吃掉"的问题。

4.3 日常内容更新流程

caveman 的内容更新流程可以说是"原始得不能再原始"。我建了一个_notes目录放 Markdown 形式的草稿,每次要发新文章,先在本地写草稿,内容确认后写一个简单的 HTML 页面模板填进去,然后在作品集或阅读笔记索引列表里加入对应链接。有时候改完 HTML 就要刷新线上页面,没有热更新、没有构建队列,过程非常直接,反而治好了我"改一行代码也要跑整套工具链"的拖延症。

为了进一步压缩发布操作的时间,我写了一个小小的 shell 脚本,自动完成上传和刷新 CDN 缓存。脚本核心逻辑其实只有几行:

#!/bin/bash echo "准备同步 caveman 站点..." rsync -avz --delete public/ u@myserver:/var/www/caveman/ curl -X POST "https://cdn.example.com/purge/preload?url=https://caveman.example.com/" echo "发布完成"

这个小脚本成了 caveman 项目里唯一的"自动化设施",它不算复杂,但把最后一点重复劳动也消掉了,让我发布新文章的心理成本降到接近于零。我特意保留了它的"简陋"形态,没有把它升级成一个完整的发布系统,因为对这个项目来说,这已经是成本的极限优化了。

5. 常见问题与避坑经验整理

5.1 没有框架,页面路由和状态同步怎么做

这是我在社区分享时被问得最多的问题。很多人习惯了前端路由和组件状态管理,很难想象一个多页面站点没有这些基础设施怎么运转。其实答案很朴素:用浏览器原生的多页面机制。

在 caveman 里,每个页面就是一个独立的 HTML 文件,用户从一个页面跳到另一个页面时,浏览器会重新加载目标页面,这是 Web 最原始的"路由"。我只需要保证每个页面都包含相同的站点头部和底部组件,让用户感觉不到页面的割裂感。页面之间如果需要传递少量状态,比如用户从哪里跳转而来,可以利用 URL 参数。因为交互场景简单,完全不需要在客户端维护复杂状态,刷新页面丢失状态的场景在纯静态内容站点里几乎不会出现。

这个方案也带来了一个额外好处:任一页面都可以被直接收藏、分享,链接天然就是页面的绝对地址,搜索引擎抓取时也能明确区分不同页面的内容主题,对 SEO 非常友好。

5.2 响应式布局的几个细节坑

纯静态站点做响应式设计,最大的问题是图片在不同屏幕尺寸下的表现。我在项目里给每个内容的图片都设置了max-width: 100%和height: auto,避免图片溢出容器,但又不能在布局中预留过大的图片占位导致小屏幕下出现大段空白。解决办法是灵活使用aspect-ratio属性为图片容器设定宽高比,让浏览器在图片加载前就知道占位尺寸,页面滚动稳定性明显提升。

表格在小屏幕上也会出问题,caveman 偶尔要做一个简单的数据对比表,我会在外层套一个带横向滚动条的容器,同时容忍在极窄屏幕上出现横向滑动。这不是最漂亮的方案,但足够可用。

还有一个容易被忽略的点是移动端的点击区域。导航菜单里的每个链接,我都保证最小高度不小于 44 像素,并用touch-action: manipulation取消dblclick缩放延迟,这些细节累计起来会给移动端用户带来明显的手感改善。

5.3 长期维护是否真的省心

  • 依赖更新:原生项目没有依赖,所以不存在 npm audit 报错、版本不兼容、新增特性导致构建失败这类问题,最大的"系统升级"就是浏览器升级,而浏览器升级会尽力保持向后兼容。
  • 代码可读性:只要 HTML 结构保持语义化、CSS 变量命名清晰、JS 注释了关键逻辑,半年后回来看代码,理解成本很低。
  • 数据备份:整个站点就是几十个文件,压缩成一个包之后我可以随手上传到任何网盘或移动硬盘,没有任何专有格式问题。
  • 内容迁移:如果某天我想换到新的博客系统,内容全是标准 HTML,转成 Markdown 或者任何格式都很方便,不像某些动态系统里会被锁定在数据库结构里。

提示:任何项目都有 " 简与繁 " 的平衡点。caveman 适合内容更新频率低、页面结构稳定、不需要复杂权限体系的场景。如果你的个人站点已经规划了会员系统、动态评论、文章搜索、多角色后台,那就不适合采用这种方案了,老实上框架才是更务实的选择。

6. 项目复盘与经验边界

caveman 上线之后我实际使用了接近半年,感受是可以明确说的:这个极端的"原始人式"方案不仅撑住了日常运营,还让我的精力大量回流到了内容本身。

我写内容时不再为技术细节分心,打开一个 HTML 文件改几段文字就能发布,这种"直接、立刻、无中间环节"的体验,正是我做这个项目的初心。当然,我也主动划清了它的边界——当某天我需要给站点加入动态搜索、评论系统、用户交互或者复杂权限的时候,我不会硬把它塞进 caveman 的框架里,而是会考虑更合适的工具,甚至直接选用成熟的动态博客系统。

最后再分享一个小技巧:如果看完这篇文章你也想动手做一个类似的极简站点,不必一开始就追求完美,先把首页和一篇作品内容搭好,放上一个真实的链接,哪怕只有一页。完成度比完美度重要得多,尤其是当你正在从复杂工具链里挣脱出来的时候,把一个能真实运行的简单页面推到线上,那种踏实感比任何技术选型论证都有说服力。这大概就是 caveman 这个项目最想传递的东西:用你自己完全看得懂、控得住的方式,把想表达的东西发布出去。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询