C05 HTML 与工程化

2026-10-31 14:470 阅读约 11 分钟HTML

摘要:单文件页面在第三个页面出现时开始失控:导航要同步改、页头重复三份、路径散落各处。工程化解决的是「同一份结构只维护一次」。本文对比四种交付方式,给出一个不依赖框架的最小构建脚本,并列出发布前必须核对的六项产物检查。
关键词:模板复用,静态生成,服务端渲染,产物检查,交付

所属:frontend/html / C-高级 | 上一篇:C04-XSS与CSP | 下一篇:D00-总结 | 返回:C00-总结

1 引言

手写 HTML 在页面数量少时效率最高,超过三个页面后维护成本转为线性增长:改一次导航,要改三个文件。工程化的本质是把重复结构抽成数据,再由脚本渲染出最终 HTML。

本文给出四种方案的取舍与一个最小实现。范围见表 1-1。

项 本文覆盖 本文不覆盖
复用 模板片段、页面数据、构建脚本 组件框架与状态管理
交付 静态托管、静态生成、服务端渲染、客户端渲染 容器编排与 CDN 配置
产物 路径、压缩、404 页、缓存头 监控与回滚流程

2 预备知识

项 要求 核对方式
环境 Node 20+ 终端执行 node -v
前置 A09 能独立写完整页面
前置 C03 了解资源路径与优先级
目录 html-practice/build/ 含 pages/ 与 partials/ 新建即可

3 原理与实现

3.1 从源文件到产物

构建只做三件事:读数据、套模板、写文件,如图 3-1 所示。

flowchart LR
    A["页面数据<br/>pages/*.json"] --> C["构建脚本"]
    B["模板片段<br/>partials/*.html"] --> C
    C --> D["渲染完整 HTML"]
    D --> E["dist/ 产物目录"]
    E --> F["静态托管<br/>nginx / 对象存储"]
    E --> G["本地打开校验"]

图 3-1 模板复用的构建流程

图上可见:产物是完全静态的 HTML,运行时不依赖构建脚本;这决定了它可以在任何静态托管上运行。

3.2 最小构建脚本

// 运行环境:Node 20+;保存为 build/build.mjs,执行 node build/build.mjs
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
import { join } from 'node:path';

const root = new URL('.', import.meta.url).pathname;
const layout = readFileSync(join(root, 'partials/layout.html'), 'utf8');

const pages = [
  { slug: 'index', title: '首页', body: '<h1>首页</h1><p>站点简介。</p>' },
  { slug: 'about', title: '关于', body: '<h1>关于</h1><p>作者与联系方式。</p>' },
];

for (const page of pages) {
  const html = layout
    .replaceAll('{{title}}', page.title)
    .replaceAll('{{body}}', page.body);
  mkdirSync(join(root, 'dist'), { recursive: true });
  writeFileSync(join(root, 'dist', `${page.slug}.html`), html, 'utf8');
  console.log(`已生成 dist/${page.slug}.html`);
}
<!-- partials/layout.html -->
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{title}} | 李明的工作笔记</title>
    <link rel="stylesheet" href="./assets/main.css" />
  </head>
  <body>
    <header><nav><a href="./index.html">首页</a> <a href="./about.html">关于</a></nav></header>
    <main>{{body}}</main>
    <footer><p>© 2026 李明</p></footer>
  </body>
</html>

四种交付方式的取舍见表 3-1。

方式 首屏内容来源 适用场景 代价
手写静态页 构建期已固定 3 页以内 重复结构,改一处改多处
静态生成 构建期渲染成 HTML 内容型站点、文档站 需要构建流程与产物管理
服务端渲染 每次请求生成 需登录态、个性化内容 需服务器与运行时
客户端渲染 浏览器中生成 强交互应用 首屏空壳,检索与分享不友好

发布前必须核对的六项见表 3-2。

序号 检查项 判定标准
1 资源路径 产物中无 ../ 越界,图片可访问
2 文档结构 每页保留 doctype、lang、charset、viewport
3 链接 站内链接全部可达,无 # 占位
4 占位符 产物中无 {{...}} 残留
5 404 页 存在 404.html,且样式与站点一致
6 体积 单个 HTML 未超预期,图片已压缩

4 验证与讨论

  1. 建立 partials/layout.html 与 build/build.mjs,执行脚本,确认生成两个页面。
  2. 打开 dist/index.html,确认导航、页脚、标题均来自模板,正文来自数据。
  3. 在产物目录搜索 {{,确认无残留占位符。
  4. 修改模板中的导航,重新构建,确认两个页面同步更新。
检查项 预期结果 说明
产物完整 两个 HTML 文件生成 脚本遍历数据
结构一致 两页头部与页脚完全相同 模板复用
无占位符残留 搜索 {{ 为 0 命中 替换逻辑覆盖全部键
本地可打开 双击产物正常渲染,无构建依赖 纯静态
路径可用 图片与样式在 dist/ 内可访问 资源需同步复制到产物

讨论与局限。 字符串替换模板无法处理循环与条件,页面数量继续增长时应引入模板引擎或静态站点生成器。另构建产物需要连同 assets/ 一起发布,仅复制 HTML 会导致样式与图片全部 404。

5 常见问题

现象 原因 处理
产物打开后无样式 assets/ 未复制到 dist/ 构建脚本增加复制步骤
占位符原样出现在页面上 数据字段名拼写与模板不一致 统一键名,构建后搜索 {{ 核验
站内链接 404 产物路径与链接写法不一致 统一相对路径,按 R22 校验
中文乱码 写入时未指定 UTF-8 writeFileSync 显式指定编码
每次构建都要手工清理旧文件 未清理产物目录 构建前删除 dist/,避免残留旧页

6 结论

序号 结论 依据
1 工程化解决「一份结构只维护一次」 图 3-1
2 静态生成适合内容型站点,交付成本最低 表 3-1
3 发布前六项检查缺一不可 表 3-2
4 产物必须自带资源,不能依赖构建环境 4 节步骤 4

参考文献

[1] MDN Web Docs · 发布网站,https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/Publishing_your_website(访问于 2026-10-29)
[2] Node.js 文档 · fs 模块,https://nodejs.org/api/fs.html(访问于 2026-10-29)

返回文章列表

评论 0

0/2000

还没有评论,快来抢沙发吧~