☰
不用后端的个人博客:纯HTML+CSS+JS源码搭建与部署指南
2026/9/26 23:00:35 网站建设 项目流程

简介:一套面向个人博客场景的 HTML+CSS 静态网页源码,适合想搭建个人展示页、记录日常或学习前端基础的博主与初学者;无需后端数据库,上传到静态托管服务即可访问。页面由 index.html 定义结构化骨架,head、header、nav、article、footer 等标签分别承担标题信息、页头、导航、文章区和页脚;style.css 统一负责字体、颜色、间距与整体布局,盒模型、浮动、定位等经典 CSS 技巧都在其中有所体现,ID 与类选择器的配合也便于理解样式组织。压缩包共 30 个文件,除 HTML 和 CSS 各 1 个外,还包含 27 个 GIF 装饰图与 1 张 JPG 照片,整体仅 37KB;GIF 素材多用作分隔线、按钮背景和页脚装饰,替换方便,整体结构清晰,适合零基础快速套用。已有 3814 人学习下载;使用者既可以对照源码拆解博客页面结构与样式写法,也可以直接换掉图片和文字,生成自己的个人博客页面,对入门者很有参考价值。

1. 一个不用后端就能跑的个人博客:HTML静态源码到底能干什么

做技术的人想搞个人博客,第一反应往往是去装 WordPress、配数据库、买服务器,结果折腾一晚上,文章还没写,环境先崩了。这套“个人博客网页设计 html 源码”要解决的,正是这个场景:它是一份纯静态的博客前端工程,不需要 PHP、不需要 MySQL,本地双击 index.html 就能预览,扔到任意支持静态页面的托管平台上就能上线。别人访问到的页面效果,和你本地看到的基本一致。

它适合三类人:第一类是前端刚起步、想找一份完整代码拆着学的,第二类是只想有个干净博客写技术笔记、不打算碰服务器运维的,第三类是拿它当课程设计或毕设演示的,改改配色、换换文章卡片就交差。这套源码的内核很简单——HTML 负责语义结构,CSS 负责布局和响应式,JS 负责滚动、返回顶部这类交互。理解这三层怎么协作,比拿到源码本身更有价值。今天这篇就把这套模板拆开,从选型逻辑讲到怎么改、怎么部署、踩过哪些坑。

2. 静态博客技术选型:HTML+CSS+JS 三层到底怎么分工

这一章先把“为什么纯 HTML 源码能撑起一个博客”讲透,再分别拆解 HTML、CSS、JS 的具体角色。只有明白三层各自的边界,你后面改代码才不会改出“样式没生效”“文章点不进去”这类问题。

2.1 为什么用静态博客而不是 WordPress

先算一笔账。WordPress 跑起来需要 Web 服务器、PHP 解释器、MySQL 数据库,最低配云服务器一年几百到几千,加上域名备案,学习成本至少一周;而静态博客只需要一堆 .html、.css、.js 文件,托管到 GitHub Pages、Gitee Pages 或对象存储上,走 HTTP 就能访问,成本为零。

静态方案在写技术博客时有个非常实际的好处:文章就是纯 HTML 片段,加载路径短,没有数据库查询,首屏渲染快。内容安全可控,不会被插件漏洞拖累,备份就是把整个目录打压缩包。缺点是动态能力弱——没有评论、没有站内搜索、没有后台编辑器。对应方案也成熟:评论用第三方脚本接入,搜索交给第三方搜索框,写作直接在本地编辑器里改 HTML 或 Markdown。

这套源码的定位就是静态方案的成品模板,省掉你自己从零搭建布局和样式的功夫。你拿到手做的第一件事,应该是摸清楚文件结构,而不是急着改样式。

2.2 HTML5 语义化标签:搜索引擎和浏览器都爱读的结构

打开源码里的 index.html,会发现它没用一堆无意义的 div 层层嵌套,而是用了完整的 HTML5 语义标签。大概结构是这样:

<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="个人博客,记录技术与生活"> <title>我的个人博客</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <header class="site-header"> <h1>我的个人博客</h1> <nav class="main-nav"> <ul> <li><a href="index.html">首页</a></li> <li><a href="archive.html">归档</a></li> <li><a href="about.html">关于</a></li> </ul> </nav> </header> <main class="content-wrap"> <article class="post-card"> <h2><a href="posts/first-post.html">第一篇博客</a></h2> <p class="post-meta">2024-12-01 · 前端</p> <p>这里是文章摘要,通常保留一到两句话。</p> <a class="read-more" href="posts/first-post.html">阅读全文</a> </article> </main> <footer class="site-footer"> <p>© 2024 我的个人博客</p> </footer> <script src="js/main.js"></script> </body> </html>

这串代码里,header告诉浏览器这里是站点头部,nav是导航区,main是主体内容,article是一篇完整的文章卡片,footer是页脚。搜索引擎爬虫对语义化标签的权重理解远高于 class 命名,这是 SEO 的地基。

<meta name="viewport">这行值得单独讲,没有它,手机浏览器会按桌面宽度渲染再缩小,页面字体小到需要双指放大。lang="zh-cn"声明页面语言,影响浏览器翻译插件和屏幕阅读器的判断。引入 CSS 用link,引入 JS 用script,两个标签都放在合理位置——CSS 在head里提前加载,JS 在body末尾避免阻塞渲染,这两条是页面性能的常识。

提示:改模板时保持lang="zh-cn"不要动,删掉它会让中文页面在部分浏览器里被误判成其他语言,连带着翻译插件也会乱来。

2.3 CSS 这一层:布局、响应式与设计变量

CSS 在这套源码里承担三件事:视觉风格、栅格布局、响应式适配。样式文件一般拆成基础重置、布局、组件、响应式四个区块,方便定位。

:root { --bg-primary: #f5f5f5; --bg-card: #ffffff; --text-primary: #333333; --accent-color: #2d6cdf; --max-width: 760px; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; background-color: var(--bg-primary); color: var(--text-primary); line-height: 1.8; } .post-card { background: var(--bg-card); max-width: var(--max-width); margin: 20px auto; padding: 24px 28px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); }

注意:root里的--bg-primary这类自定义属性,这是 CSS 变量,全站颜色、间距、最大宽度都统一从这几个变量取值。想换主题色,找到--accent-color: #2d6cdf改成你喜欢的色值,所有用到它的按钮、链接、高亮文字会同步变色,不用一个一个找。

响应式的关键是媒体查询。这套源码一般在文件末尾有一段针对小屏的适配规则:

@media (max-width: 768px) { .content-wrap { padding: 0 14px; } .post-card { padding: 16px 18px; margin: 12px auto; } .main-nav ul { flex-direction: column; gap: 8px; } }

代码逻辑不复杂:屏幕宽度低于 768 像素时,缩减页面内边距、卡片留白,导航从横排变竖排。Media 查询本身是增量覆盖,写在小屏规则里的属性会盖掉正常宽度下的同名属性,优先级和源码顺序有关,所以响应式规则建议统一放在文件最后。

2.4 JavaScript 交互:博客里真正“能动”的部分

纯 HTML 和 CSS 做出来的页面是静态的,JS 负责让博客有反馈感。这套模板里的 js/main.js 通常包含几段功能:移动端菜单开关、点击回到顶部、导航栏滚动加阴影。核心逻辑可以拆成下面这样:

// 移动端菜单开关 const menuToggle = document.querySelector('.menu-toggle'); const navMenu = document.querySelector('.main-nav ul'); menuToggle.addEventListener('click', () => { navMenu.classList.toggle('active'); }); // 回到顶部按钮 const backTopBtn = document.getElementById('back-top'); window.addEventListener('scroll', () => { if (window.scrollY > 400) { backTopBtn.style.display = 'block'; } else { backTopBtn.style.display = 'none'; } }); backTopBtn.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); });

第一段给“菜单按钮”绑定了点击事件,点击时给导航列表加一个active类,CSS 里对应display: none和display: flex的切换完成展开收起。第二段监听滚动事件,滚动超过 400 像素显示回到顶部按钮,点击后用scrollTo配合behavior: 'smooth'平滑滚回顶部。

写原生 JS 时要养成好习惯:每个querySelector拿到元素后先确认不是 null 再挂事件。如果页面某处删掉了对应元素,JS 直接报错,后面所有逻辑都会停摆。把addEventListener包在if判断里是最朴素的防御。

注意:滚动事件本身触发频率极高,如果回调里有复杂的 DOM 操作或样式读写,会有明显的性能损耗。实战中做节流处理——用requestAnimationFrame或setTimeout限制回调在每一帧内只执行一次。

3. 把这套源码跑起来:目录结构、改篇文章、调个样式

这章进入实操。从解压后的目录结构讲起,到本地预览、替换成你自己的文章、改颜色,最后把站点推上线上平台。每一步都会解释命令在干什么,参数怎么改。

3.1 本地预览:双击打开和本地服务器的差别

拿到源码压缩包,解压后第一件事是在本地确认它能跑。最常见的操作是双击 index.html,浏览器会以file://协议打开。这样看静态效果完全没问题,但有两个隐患:浏览器对本地文件的 XHR 请求有限制,有些 JS 特效和加载外部数据的功能会静默失败;地址栏里的路径是本地磁盘路径,和线上 URL 不同,涉及根路径引用时容易踩坑。

推荐的做法是在源码目录下起一个本地 HTTP 服务。如果你装了 Python,一行命令就能搞定:

# 在源码根目录执行 cd your-blog-source python3 -m http.server 8080

命令执行后,打开浏览器访问http://localhost:8080,就能看到和线上几乎一致的效果。8080是端口号,如果被占用,换成 8081、8090 都可以。python3 -m http.server会把你当前所在的目录作为站点根目录提供服务,好处是 JS、CSS、图片资源都按相对路径正常加载,和线上行为一致。

没有 Python 也没关系,前端开发常用的 Node.js 同样轻量:

npx serve -l 8080 .

这句命令从 npm 临时拉取 serve 包并启动,.代表当前目录作为站点根目录。临时启动不会污染全局环境,适合只是简单预览的场景。

3.2 从源码到一篇能看的新文章:DOM 结构拆解

预览没问题后,先别急着改样式,第一件事应该是替换成自己的内容。找 index.html 里的文章卡片部分,它通常是这类结构:

<article class="post-card"> <div class="post-cover"> <img src="images/cover-1.jpg" alt="封面图"> </div> <div class="post-body"> <span class="post-category">技术笔记</span> <h2 class="post-title"> <a href="posts/nginx-config.html">Nginx 配置踩坑记录</a> </h2> <p class="post-excerpt"> 这篇文章记录了我在给博客配置 Nginx 时遇到的几个典型问题,包括路径匹配优先级、缓存策略和 404 排查思路。 </p> <div class="post-meta"> <span class="post-date">2024-11-20</span> <span class="post-author">Evan</span> </div> </div> </article>

把标题、日期、摘要换成你自己的内容,把href指向你新建的文章页面,首页这一个卡片就算改完了。新建单篇文章有一个约定:文件命名里不要带空格和中文,一律用小写字母加连字符,比如nginx-config.html。原因是线上服务器对带空格和中文字符的 URL 要做编码,手一抖编码格式混了就 404。

粘贴文章内容时,保持标题层级清晰:单篇文章页面里只有一个<h1>主标题,下面按h2 -> h3往下排。文件内的图片路径建议用相对路径,比如../images/pic-1.jpg,这样整个博客目录拷到任何地方,路径都不会断掉。

3.3 换配色和字体:CSS 变量让整站只改两行

模板默认的配色不一定是你要的。这套源码如果用了 CSS 变量,换主题色就是改几个变量的事。日志文件大概长这样:

:root { --accent-color: #2d6cdf; --text-primary: #333333; --text-secondary: #888888; --bg-card: #ffffff; }

把--accent-color换成#e65c41之类暖色,全站按钮、链接、标签底色同步更新。--text-primary是正文主色,控制文章可读性,不建议调太浅——很多看博客的人是在晚上,灰色文字在暗背景下直接看不清。

字体方面,正文通过 font-family 的候选列表实现不同系统下的最优显示:

body { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif; }

这个列表是逐个尝试:苹果设备命中-apple-system,Windows 命中Microsoft YaHei,Linux 命中Noto Sans SC,最后兜底无衬线体。想引入思源宋体这类外部字体,需要额外引入字体文件,改动量和收益看个人喜好,先用系统字体栈不会出错。

3.4 把博客推到线上:三种免费托管方式对比

本地改完,最终要上线。静态博客托管有三种主流选择,参数对比如下:

托管平台仓库要求自定义域名HTTPS国内访问速度
GitHub Pages公开仓库支持自动一般,不稳定
Gitee Pages公开仓库支持自动快
Cloudflare Pages连接 Git 仓库支持自动快,偶尔波动

最省事的方式是推 GitHub。首次在项目目录执行:

git init git add . git commit -m "init blog" git branch -M main git remote add origin https://github.com/你的用户名/你的仓库名.git git push -u origin main

推送成功后,进入仓库的 Settings -> Pages,Source 选Deploy from a branch,分支选main,目录选根目录,保存后等待一两分钟,博客就会出现在https://你的用户名.github.io/仓库名下。

国内访问 GitHub Pages 速度不稳定,想要稳定快速就选 Gitee Pages 或 Cloudflare Pages。Gitee Pages 需要先实名认证,仓库转换成 Gitee Pages 服务后每次更新代码要在控制台手动点一次“更新”。Cloudflare Pages 国内访问大体顺畅,不需要备案,是技术博客圈子的常用方案。如果完全不想碰命令行,也有静态托管服务支持直传文件夹,但 Git 方式是主流,建议还是花半小时熟悉基本命令——这属于早晚要补的一课。

4. 个人博客 HTML 源码避坑:路径、编码、兼容性三条主线

代码能跑是前提,跑起来不翻车才叫稳。这里把改博文、换主题过程中最容易出现的几类翻车事故整理出来,每条都按“现象、原因、解决”写清楚。

4.1 页面打开了但样式全丢

现象:浏览器能显示文字和图片,但布局完全裸奔,没有背景色、没有卡片圆角、导航横排也全部失效。

原因:最常见的是css/style.css的路径引用断了。比如把 index.html 直接从项目根目录复制到了 posts 子目录,原来href="css/style.css"是相对路径,在 posts 目录里会去查找posts/css/style.css,自然找不到。也有可能是本地预览时用file://协议直接打开,而 CSS 文件内部有用绝对根路径引用的额外资源。

解决:确认 index.html 和 css 目录的相对关系。项目结构里 index.html 与 css、js、images 平级时,用href="css/style.css";如果 HTML 文件在二级目录里,要写成../css/style.css。把网站部署上线后,打开浏览器开发者工具(F12)切到 Network 面板,刷新页面看有没有红色标红的样式请求,只要 404 的 URL 出现在那里,路径问题一目了然。

提示:改 HTML 内部引用路径时,养成“从根目录视角推一遍”的习惯。站在目标 HTML 文件的位置,看要引用的资源在哪个方向,一级目录用./开头,上一级用../开头,这个思路比死记硬背可靠得多。

4.2 中文文章标题全部变成问号或乱码

现象:浏览器里看文章列表、页面标题、摘要都是正常的,但单独打开某篇文章,中文变成一堆方块或问号。

原因:HTML 文件本身没有保存为 UTF-8 编码,或者文件缺了<meta charset="UTF-8">声明。用 Windows 自带的记事本或者某些默认使用 GBK 编码的编辑器修改文件后,保存时编码变了,浏览器按 UTF-8 解析就会出乱码。

解决:设置编辑器默认保存编码为 UTF-8。VS Code 的右下角有“UTF-8”按钮,点击后选择“Save with Encoding”并选择 UTF-8;纯文本编辑器则可能需要在另存时手动选编码。改完之后,确认 head 区有<meta charset="UTF-8">,并且在 HTML 里不要出现charset="gb2312"这样的旧声明。

4.3 手机上看布局被挤压变形

现象:手机浏览器打开页面,文字没有自动适应屏宽,横向滚动条出现,卡片充满整个屏幕但边距非常窄。

原因:缺 viewport 设置是头号嫌疑。没有<meta name="viewport" content="width=device-width, initial-scale=1.0">这行,移动端浏览器默认按 980 像素的虚拟画布渲染,然后把页面整体缩小,观感上就是字小、布局挤。另一种可能是媒体查询的断点没覆盖到当前机型,比如只写了 768px 断点,有些手机宽度超过这个值,平板横屏也会不触发小屏样式。

解决:先确认 head 里 viewport 标签存在。再看媒体查询的断点是否合理——一般覆盖 360px 到 768px 区间就够用了,常用断点可以设为 768px 一个中档断点。调样式时把浏览器窗口拖到窄宽度,实时看效果,比在真机上一遍遍刷新效率高。

4.4 图片加载慢,页面整体卡顿

现象:博客文章里插了几张大图,打开时图片一点点从顶部往下加载,页面滚动时明显掉帧,甚至图片区域空白很久。

原因:图片没有经过压缩,原图直接放进 images 目录。相机或设计稿导出的图片动辄 2MB 起步,请求一个 2MB 的文件比请求 50KB 的文件慢几十倍;多张大图一起加载,带宽和内存双吃紧。也不排除图片尺寸远远超过了展示尺寸,宽 4000 像素的图被 CSS 压缩显示成 600 像素,浪费资源。

解决:文章配图在放入项目之前,先压一轮。规则很简单:图片显示宽度是 600 像素,就导出 600 像素宽的图;显示宽度是 1200 像素,就导出 1200 像素。保存格式按需选,摄影图用 JPEG,截图和图形界面用 PNG 或 WebP。大小控制到 200KB 以下最稳。压缩工具用任何一个在线的都行,或者用本地命令行工具批量处理:

# 已安装 ImageMagick 时,批量压缩文件夹内所有 jpg mogrify -resize 1200x -quality 82 images/*.jpg

-resize 1200x强制最大宽度 1200 像素,高度等比例缩放;-quality 82是 JPEG 压缩质量,80 到 85 区间肉眼看不出明显劣化,体积能减一半以上。图片尺寸和体积处理好之后,再考虑要不要加懒加载——用loading="lazy"属性让图片滚到视口附近才开始加载,一页几十张图也不会卡。

4.5 改了代码刷新页面没变化,怀疑浏览器“记忆”了旧版本

现象:改完 CSS 或 JS,刷新页面还是旧样式、旧交互,控制台里也看不到报错。

原因:浏览器缓存了 CSS 和 JS 文件。静态文件通常带有缓存策略,尤其部署到托管平台后,平台会自动给静态资源打长缓存时间的标记。本地预览时,也有小概率是编辑器的自动保存没触发,改了但文件没写进磁盘。

解决:本地调试时强制刷新,Windows 用 Ctrl+F5,Mac 用 Cmd+Shift+R,这会绕过缓存重新拉资源。部署到线上后遇到这个问题,处理方式是给资源加载加版本参数。比如:

<link rel="stylesheet" href="css/style.css?v=20250106"> <script src="js/main.js?v=20250106"></script>

?v=后面跟日期或版本号,参数变化后浏览器把它当作新 URL,强制重新下载。这个习惯值得长期保持,每次发布改一下版本号,比让用户手动清缓存靠谱。还有一种情况:Git 提交了但没推送到远端仓库,线上是旧版本——检查本地 commit 和远程仓库的差异。

5. 进阶玩法:让静态博客自动生成文章列表,上线前五项验证

静态博客的短板是“文章得手写 HTML 卡片再塞进首页”。本节给一个轻量方案:用原生 JS 配合一份 JSON 配置,让首页文章列表自动渲染;再从性能、SEO、链接三个维度做上线前的验证。一套流程走完,这套模板就真正变成你自己的博客系统了。

5.1 用一小段原生 JS 自动渲染文章索引

思路是:把文章元数据(标题、链接、日期、分类、封面图、摘要)放进一个data/posts.json;index.html 里的文章卡片容器留空,页面加载后用fetch拉取 JSON,循环拼出卡片 DOM 插入页面。

新建data/posts.json,与 index.html 平级目录:

[ { "title": "Nginx 配置踩坑记录", "url": "posts/nginx-config.html", "date": "2024-11-20", "category": "技术笔记", "cover": "images/cover-1.jpg", "excerpt": "记录配置 Nginx 时的几个典型问题。" }, { "title": "从零开始搭建个人博客", "url": "posts/blog-setup.html", "date": "2024-12-01", "category": "随笔", "cover": "images/cover-2.jpg", "excerpt": "聊聊选型、写文章和部署的整体流程。" } ]

这里每一项就是一个文章的展示字段,后续加文章只需在数组里加一个对象。日期字段建议用YYYY-MM-DD这种可排序格式,后面渲染时可以按 date 倒序排。

然后在 js/main.js 里加一段渲染逻辑:

fetch('data/posts.json') .then(res => { if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); }) .then(posts => { const container = document.querySelector('.posts-list'); if (!container) return; const html = posts.map(post => ` <article class="post-card"> <div class="post-cover"> <img src="${post.cover}" alt="${post.title}"> </div> <div class="post-body"> <span class="post-category">${post.category}</span> <h2 class="post-title"> <a href="${post.url}">${post.title}</a> </h2> <p class="post-excerpt">${post.excerpt}</p> <div class="post-meta"> <span class="post-date">${post.date}</span> </div> </div> </article> `).join(''); container.innerHTML = html; }) .catch(err => console.error('文章列表加载失败:', err));

代码逻辑分三段:第一步先fetchJSON 文件,res.ok用于判断 HTTP 状态码,非 2xx 直接抛错;第二步拿到数组后遍历生成 HTML 模板字符串,最后一次性把整段 HTML 塞进容器。用map加join('')避免末尾多逗号,比forEach拼接更干净。

模板字符串里的${}要注意安全边界:如果标题或摘要里带了引号、尖括号,直接嵌进 HTML 可能破坏结构。三个防护习惯:一是内容自己可控时,保证 JSON 里不写<script>这类标签;二是渲染前做一次字符转义;三是在 index.html 预留容器时给一个空节点,渲染失败也不影响页面主体。

5.2 用脚本把文章数据抽成 JSON

上面那段逻辑假设你手动维护 posts.json。文章少可以,文章多了手写容易漏字段。更省力的方式是用 Node.js 脚本扫描文章目录,自动生成 JSON。熟悉命令行的可以挂一个定时任务,这里给出一个最小可用的脚本:

// scripts/gen-posts-json.js const fs = require('fs'); const path = require('path'); const postsDir = path.join(__dirname, '../posts'); const outputFile = path.join(__dirname, '../data/posts.json'); const posts = fs.readdirSync(postsDir) .filter(file => file.endsWith('.html')) .map(file => { const fullPath = path.join(postsDir, file); const content = fs.readFileSync(fullPath, 'utf-8'); // 从 HTML 文件中提取 <title> 和首个 <meta name="description"> const titleMatch = content.match(/<title>([^<]+)<\/title>/); const descMatch = content.match(/<meta name="description" content="([^"]+)"/); const dateMatch = content.match(/<time datetime="([^"]+)"/); return { title: titleMatch ? titleMatch[1] : file, excerpt: descMatch ? descMatch[1] : '', date: dateMatch ? dateMatch[1] : '', url: `posts/${file}` }; }) .sort((a, b) => b.date.localeCompare(a.date)); fs.writeFileSync(outputFile, JSON.stringify(posts, null, 2)); console.log(`已生成 ${posts.length} 篇文章的索引`);

运行方式:

node scripts/gen-posts-json.js

脚本做的事情并不玄:读 posts 目录下所有 .html 文件,逐一用正则抽取<title>、description、<time datetime>,字段缺了就给空字符串兜底,按日期从新到旧排序,最后写到 posts.json。文章分类、封面这些字段不在 HTML 里,需要额外约定写进每个文章的页面内,或者干脆在脚本里用一个规则表映射文件名到分类。这种脚本的好处是,新文章写好后跑一次,首页列表就自动更新,不用手动改 index.html。

5.3 部署后必做的五项验证

部署完成并不能代表万事大吉,上线后按下面五条逐一过一遍,基本能保证常态可用:

第一,选一篇文章走通整个访问链路。点击首页卡片进入文章详情页,确认文章页的 CSS 也正常。有些模板详情页是单独的设计,漏引用 CSS 文件会让文章页裸奔。地址栏里的 URL 如果带.html后缀,属于正常静态页面;如果显示posts/结尾没有扩展名,可能是平台做了美化路由,后续上传文件时注意保持目录结构一致。

第二,检查图片引用是否全部可访问。进入文章详情页,打开开发者工具或直接右键图片检查,逐个确认图片来源是正常 200 还是 404。常见问题是图片存放在 images 根目录,而文章在 posts 子目录,引用路径写成了images/xx.jpg,这里必须写成../images/xx.jpg。

第三,确认网站标题和描述正确显示。浏览器标签页上显示的标题就是<title>里的内容。用微信或者钉钉把链接发给同事,看聊天窗口里的预览卡片是否显示了正确的标题、描述和缩略图。没有缩略图时,在 head 区添加一张og:image的 meta 标签指向封面图,社交平台一般会有缓存,第一次预览不生效,过几分钟再看。

第四,跑一次基础 SEO 检查。把线上 URL 贴到搜索引擎的抓取模拟工具里,确认能拿到 200 状态和页面内容。重点确认首页<title>不要和文章页重复,博客标题加上文章标题是更合理的组合,比如文章标题 - 博客名这种结构。

第五,全站走一遍小屏适配。用手机或开发者工具的手机模拟模式打开首页、文章页、归档页各扫一眼,重点看导航、卡片、图片有没有横向溢出。移动端访问占比在技术圈子里并不低,这步不要省。

这套模板用顺手之后,建议给自己固定一套发布流程:写完文章 HTML 文件,放对目录;跑一次生成 JSON 的脚本;本地起服务预览一遍;推 Git;上线后再跑一遍上面五项验证。我做这套流程用了大半年,中间翻过车——有一阵往 JSON 里塞了未转义的双引号,整个首页文章列表直接空白,控制台报语法错误。从那以后,每次更新 posts.json 后我都要在浏览器控制台确认 fetch 返回的数组长度和文章数对得上,再继续做别的。这已经是刻进肌肉记忆的习惯,希望这套流程也能帮到你少踩几个坑。

本文还有配套的精品资源,点击获取

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

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

立即咨询