
不是教你背标签,而是帮你把 HTML 学对
很多初学者学习 HTML 时,容易陷入"背标签"的节奏:记住几个常用元素,能写出一个简单页面,就觉得自己掌握了。但一旦涉及到语义化、属性分类、内容模型、可访问性等稍微深入的知识点时,就开始混乱。
问题不在于 HTML 难,而在于学习顺序常常不对。
HTML 不是标签的简单堆砌,而是一套描述文档结构与语义的标准。今天这篇文章,我希望能帮你站在规范的视角重新理解 HTML:它是什么、页面为什么这样组织、元素和属性如何分类、哪些写法只是"能跑",哪些才是"规范而专业"的。
本文主要参考 WHATWG 维护的 HTML Living Standard 和 MDN Web Docs。
一、HTML 到底是什么

1.1 定义与定位
HTML(HyperText Markup Language,超文本标记语言)是一种用于描述网页内容和结构的标记语言,它不是编程语言。HTML 通过预定义的标签来标记文本、图片、多媒体以及可交互元素,使浏览器能够正确解析并呈现这些内容。
HTML 与 CSS、JavaScript 共同构成现代 Web 技术的三大基石:
| 技术 | 职责 | 通俗理解 |
|---|---|---|
| HTML | 定义文档结构与语义 | "这是什么" |
| CSS | 控制视觉样式与布局 | "它长什么样" |
| JavaScript | 提供交互与动态逻辑 | "它怎么动" |
1.2 HTML 的核心思维方式
HTML 最重要的思维方式是:先表达语义,再考虑样式和交互。
来看一个例子:
html
<!-- 好的写法:语义明确 -->
<p lang="zh-CN">这是一个段落。</p>
<!-- 不好的写法:只关注显示效果 -->
<div style="margin: 1em 0;">这是一个段落。</div>
第一段代码表达的是:"这里有一个段落,这段内容的语言是中文"。第二段只表达了:"这里有一块文字,上下边距是 1em"。
这就是 HTML 的核心:通过语义化的标记,让内容本身具有明确的意义,而不是只关注它"看起来像什么"。
1.3 HTML 发展简史
了解 HTML 的发展历程,有助于理解为什么某些特性存在、为什么有些写法被废弃。
| 时间 | 事件 | 意义 |
|---|---|---|
| 1989.03.12 | Tim Berners-Lee 在 CERN 提交《信息管理:提案》 | WWW 概念诞生,奠定 HTML 理论基础 |
| 1990.12 | 首个网页浏览器/服务器 WorldWideWeb 上线 | HTML 首次实现,首个网站 info.cern.ch 运行 |
| 1991.08 | HTML 标签首次公开发布(18个标签) | HTML 正式走向公众,包含 <a>、<p>、<h1>-<h6> 等基础标签 |
| 1993.06 | HTML 1.0 作为 IETF 工作草案发布 | 首份公开规范草案(非正式标准) |
| 1995.11.24 | HTML 2.0 成为 IETF 正式标准(RFC 1866) | 首次标准化,确立表单、表格等核心功能 |
| 1997.01.14 | HTML 3.2 发布(W3C Recommendation) | 标准化浏览器扩展(表格、图像、脚本等),结束浏览器大战混乱期 |
| 1997.12.18 | HTML 4.0 发布(W3C Recommendation) | 引入 Strict/Transitional/Frameset 三种文档类型,支持 CSS 样式分离 |
| 1999.12.24 | HTML 4.01 发布(W3C Recommendation) | 最后一个 HTML 4 系列版本,修正 4.0 错误,至今仍是稳定基准 |
| 2000.01 | XHTML 1.0 发布 | XML 与 HTML 结合,要求严格语法,但未能取代 HTML |
| 2004 | WHATWG 成立,启动 HTML5 开发 | 浏览器厂商联合反抗 W3C 的 XHTML 2.0 路线,追求向后兼容与现实兼容性 |
| 2006 | W3C 放弃 XHTML 2.0,重启 HTML 工作组 | Tim Berners-Lee 承认 XHTML 路线错误,与 WHATWG 合作 |
| 2008.01 | HTML5 首份公开工作草案发布 | W3C 正式接纳 WHATWG 草案,开启标准化流程 |
| 2014.10.28 | HTML5 成为 W3C 正式推荐标准 | 引入 <video>、<canvas>、语义化标签、本地存储等,推动响应式设计与富应用时代 |
| 2019.05.28 | HTML Living Standard 确立 | W3C 与 WHATWG 签署谅解备忘录,WHATWG 成为唯一维护者,标准持续演进,不再使用版本号 |
自 2019 年起,HTML 以 Living Standard 形式持续更新,不再有"HTML6"这样的版本号。这意味着 HTML 会持续演进,而不是每几年发布一个大版本。
二、标准 HTML 文档结构
无论页面多复杂,HTML 文档的基础骨架都是稳定的。
2.1 完整示例
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>
<meta name="description" content="页面描述,用于SEO">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>页面主标题</h1>
<nav>导航区域</nav>
</header>
<main>
<article>
<h2>文章标题</h2>
<p>文章内容...</p>
</article>
</main>
<footer>
<p>© 2026 我的网站</p>
</footer>
</body>
</html>
2.2 各部分详解
<!DOCTYPE html>
- 作用:告诉浏览器使用标准模式解析文档
- 注意:缺失会导致浏览器进入"怪异模式",渲染行为与标准不一致
<html>
- 作用:HTML 文档的根元素
lang属性:声明文档主要语言,影响 SEO、屏幕阅读器发音、浏览器拼写检查
html
<html lang="zh-CN"> <!-- 简体中文 -->
<html lang="en"> <!-- 英文 -->
<html lang="zh-TW"> <!-- 繁体中文 -->
<head>
- 作用:包含文档的元数据,不直接显示在页面中
- 常见子元素
<meta charset="UTF-8">:声明字符编码。MDN 指出,HTML5 文档里字符集声明应使用 UTF-8<title>:页面标题,显示在浏览器标签页<meta name="description">:页面描述,影响搜索摘要<meta name="viewport">:控制移动端视口行为<link>:引入外部资源(CSS、图标等)<style>:内嵌 CSS 样式<script>:引入或编写 JavaScript
<body>
- 作用:网页可见内容的容器
- 特点:一个文档只能有一个 ,包含所有用户可见内容
三、HTML 元素:页面的构建块
3.1 元素的组成部分

一个完整的 HTML 元素包含四个部分:
开始标签(Opening tag)
- 格式:
<tagname> - 作用:标识元素的开始
- 示例:
<p>、<div>、<input>
属性(Attribute)
- 位置:开始标签内
- 格式:
- 标准形式:
name="value" - 布尔属性:只需属性名(如
disabled、checked) - 无引号:
name=value(不推荐) - 单引号:
name='value'
- 标准形式:
内容(Content)
- 文本内容:纯文本节点
- 嵌套元素:其他 HTML 元素
- 混合内容:文本 + 元素
结束标签(Closing tag)
- 格式:
</tagname> - 作用:标识元素的结束
3.2 空元素
3.2.1 什么是空元素
空元素(Void Elements)是指不能包含任何内容(包括文本或其他元素),并且在 HTML 语法中不需要结束标签的元素。
3.2.2 完整的空元素列表
| 元素 | 用途 |
|---|---|
<area> |
图像映射区域 |
<base> |
文档基础 URL |
<br> |
换行 |
<col> |
表格列属性 |
<embed> |
外部内容嵌入 |
<hr> |
主题分隔 |
<img> |
图像 |
<input> |
表单输入控件 |
<link> |
外部资源链接 |
<meta> |
元数据 |
<source> |
媒体资源 |
<track> |
文本轨道 |
<wbr> |
可选换行位置 |
3.2.3 语法详解
HTML 语法(推荐)
html
<!-- 标准写法:无斜杠 -->
<br>
<img src="photo.jpg" alt="描述">
<input type="text" name="username">
<!-- 带属性的空元素 -->
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<source src="video.mp4" type="video/mp4">
XML/XHTML 兼容语法(可选)
html
<!-- 兼容 XHTML/XML 的自闭合写法 -->
<br />
<img src="photo.jpg" alt="描述" />
<input type="text" name="username" />
规范说明 :HTML 解析器会将
<br />视为<br>,斜杠前的空格是可选的,但推荐加空格以提高 XHTML 兼容性(虽然现代 HTML5 不需要)。
四、HTML 属性:为元素提供额外信息
4.1 属性写法基本原则
html
<!-- 基本语法 -->
<element 属性名="属性值">
<!-- 多个属性用空格分隔 -->
<input type="text" id="username" required>
<!-- 布尔属性:只写属性名即表示 true -->
<input disabled>
<input disabled=""> <!-- 等效 -->
<input disabled="disabled"> <!-- 等效 -->
三条核心建议:
- 属性名统一使用小写
- 属性值始终加引号(双引号或单引号)
- 多个属性之间只用空格分隔
4.2 属性分类体系
4.2.1 全局属性
所有 HTML 元素都可以使用的属性(部分属性在特定元素上可能无实际效果,但语法上允许)
核心属性
| 属性 | 作用 | 示例 |
|---|---|---|
id |
唯一标识符 | <div id="header"> |
class |
类名集合 | <div class="container main"> |
title |
鼠标悬停时的提示文本 | <abbr title="HyperText Markup Language">HTML</abbr> |
lang |
元素内容的语言 | <p lang="zh-CN">中文段落</p> |
hidden |
隐藏元素 | <div hidden>隐藏内容</div> |
tabindex |
键盘 Tab 聚焦顺序 | <div tabindex="0">可聚焦的div</div> |
style |
内联 CSS 样式 | 不推荐使用 |
contenteditable |
是否可编辑 | <div contenteditable="true">可编辑区域</div> |
data-* 自定义数据属性
data-* 是 HTML5 引入的一种机制,允许开发者在标准 HTML 元素上存储自定义的私有数据,供 JavaScript 使用,同时保持 HTML 的有效性。
命名规则
| 规则 | 说明 | 示例 |
|---|---|---|
| 前缀 | 必须以 data- 开头 |
data-id |
| 小写 | 属性名必须全部小写 | data-role |
| 连字符分隔 | 多个单词用连字符 - 连接 |
data-user-name |
| 合法字符 | 只能包含小写字母、数字、连字符、句点、冒号 | data-user-role1 |
| 禁止 | 不能出现大写字母 | data-user-Role |
命名转换规则
HTML 中的连字符命名会自动转换为 JavaScript 的驼峰命名:
html
<!-- HTML 中 -->
<div data-user-id="123" data-role-type="admin"></div>
js
// JavaScript 中访问(驼峰式)
element.dataset.userId // "123"
element.dataset.roleType // "admin"
使用方式
HTML 中定义
html
<!-- 基础用法 -->
<div data-id="123">内容</div>
<!-- 存储复杂数据(建议用 JSON 字符串) -->
<div data-config='{"theme":"dark","lang":"zh"}'>内容</div>
<!-- 布尔值建议用字符串 -->
<button data-loading="true" data-disabled="false">提交</button>
<!-- 多单词属性名 -->
<article data-author-name="张三" data-publish-date="2024-01-01">...</article>
JavaScript 中访问
方法一:使用 dataset 属性(推荐)
js
const element = document.querySelector('[data-id]');
// 读取
console.log(element.dataset.id); // "123"
// 设置
element.dataset.status = 'active'; // 自动创建 data-status
// 删除
delete element.dataset.status; // 移除 data-status
// 判断存在性
console.log('userId' in element.dataset); // true/false
方法二:使用标准属性方法(兼容旧浏览器)
js
// 获取
element.getAttribute('data-user-id'); // "123"
// 设置
element.setAttribute('data-status', 'pending');
// 删除
element.removeAttribute('data-status');
事件处理器属性
共 50+ 个,格式为 on*,例如:
onclick,ondblclick,onmousedown,onmouseuponkeydown,onkeyup,onkeypressonfocus,onblur,onchange,oninputonload,onerror,onresize,onscroll
4.2.2 专有属性
只适用于特定元素的属性。
布尔属性
属性存在即表示 true,缺失即表示 false。
常见布尔属性:disabled、checked、required、readonly、multiple、hidden、autofocus
html
<!-- 以下写法都表示禁用状态 -->
<input disabled>
<input disabled="">
<input disabled="disabled">
<!-- 注意:不是写成 "true"/"false" -->
<input disabled="false"> <!-- 这仍然表示禁用! -->
枚举属性
从一组有限的关键字中取一个值。
| 属性 | 可选值 |
|---|---|
dir |
ltr、rtl、auto |
contenteditable |
true、false、plaintext-only |
translate |
yes、no |
type(<input>) |
text、email、password、number、date 等 |
URL 属性
值是指向资源的 URL(可相对或绝对路径)
src(<img>、<script>、<iframe>)href(<a>、<link>)action(<form>)
令牌集合属性
值是空格分隔的关键字或标识符列表,顺序可能有意义也可能无关,具体由规范定义。
rel(<a>、<link>):nofollow、noopener、stylesheet等class(全局属性):类名集合
数字 / 范围属性
cols、rows(<textarea>):列数、行数min/max/step(<input type="number">):最小值、最大值、步长width/height(<img>、<video>)
属性参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes
五、内容模型:理解元素如何嵌套
内容模型用于描述该元素的预期内容。一个 HTML 元素的内容必须符合其内容模型所规定的要求。
5.1 nothing 内容模型
当一个元素的内容模型为 nothing 时,该元素不得包含任何 Text 节点(元素间空白符除外),也不得包含任何元素节点。
为方便起见,大多数内容模型为 nothing 的 HTML 元素同时也是空元素。
注意:nothing 内容模型与空元素是两个独立概念:
- nothing 是内容模型层面的约束
- 空元素是语法层面的优化
5.2 内容类型
HTML 中的每个元素均属于零个或多个类别,这些类别将具有相似特性的元素归组。
- 元数据内容(Metadata content)
- 流内容(Flow content)
- 分区内容(Sectioning content)
- 标题内容(Heading content)
- 短语内容(Phrasing content)
- 嵌入内容(Embedded content)
- 交互内容(Interactive content)
这些类别之间的关系如下图所示:

- 分区内容、标题内容、短语内容、嵌入内容和交互内容均属于流内容的子类型。
- 元数据内容有时也属于流内容。
- 元数据内容和交互内容有时属于短语内容。
- 嵌入内容同时属于短语内容的子类型,并且有时也属于交互内容。
5.2.1 元数据内容
元数据内容是指用于设置其余内容的呈现或行为、定义当前文档与其他文档之间的关系,或传递其他不直接显示在页面上、但浏览器和搜索引擎需要知道的信息的内容。
<base>、<link>、<meta>、<noscript>、<script>、<style>、<template>、<title>
5.2.2 流内容
大多数在文档和应用程序主体中使用的元素都被归类为流内容。
<a>、<abbr>、<address>、<area>(如果它是 map 元素的后代)、<article>、<aside>、<audio>、<b>、<bdi>、<bdo>、<blockquote>、<br>、<button>、<canvas>、<cite>、<code>、<data>、<datalist>、<del>、<details>、<dfn>、<dialog>、<div>、<dl>、<em>、<embed>、<fieldset>、<figure>、<footer>、<form>、<h1>、<h2>、<h3>、<h4>、<h5>、<h6>、<header>、<hgroup>、<hr>、<i>、<iframe>、<img>、<input>、<ins、<kbd>、<label>、<link>(如果允许出现在 body 中)、<main>(如果它是层次结构正确的 main 元素)、<map>、<mark>、MathML <math>、<menu>、<meta>(如果存在 itemprop 属性)、<meter>、<nav>、<noscript><object>、<ol>、<output>、<p>、<picture>、<pre>、<progress>、<q>、<ruby>、<s>、<samp>、<script>、<search>、<section>、<select>、<slot>、<small>、<span>、<strong>、<sub>、<sup>、SVG <svg>、<table>、<template>、<textarea>、<time>、<u>、<ul>、<var>、<video>、<wbr>、自主自定义元素、Text
5.2.3 分区内容
分区内容是指用于定义 header 和 footer 元素作用范围的内容。
<article>、<aside>、<nav>、<section>
5.2.4 标题内容
标题内容用于定义节的标题,无论该节是使用分区内容元素显式标记的,还是由标题内容本身隐式定义的。
<h1>、<h2>、<h3>、<h4>、<h5>、<h6>、<hgroup>(前提是它包含后代 h1 至 h6 元素)
5.2.5 短语内容
短语内容是文档中的文本,以及在段落内部级别标记这些文本的元素。连续的短语内容构成段落。
<a>、<abbr>、<area>(如果它是 map 元素的后代)、<audio>、<b>、<bdi>、<bdo>、<br>、<button>、<canvas><cite>、<code>、<data>、<datalist>、<del>、<dfn>、<em>、<embed>、<i>、<iframe>、<img>、<input>、<ins>、<kbd>、<label>、<link>(如果允许出现在 body 中)、<map>、<mark>、MathML <math>、<meta>(如果存在 itemprop 属性)、<meter>、<noscript>、<object>、<output>、<picture>、<progress>、<q>、<ruby>、<s>、<samp>、<script>、<select>、slot、<small>、<span>、<strong>、<sub>、<sup>、SVG <svg>、<template>、<textarea>、<time>、<u>、<var>、<video>、<wbr>、自主自定义元素、Text
大多数被归类为短语内容的元素,其内部只能包含同样被归类为短语内容的元素,而不能包含任意的流内容。
5.2.6 嵌入内容
嵌入内容是指将外部资源导入文档的内容,或是将来自其他词汇表的内容插入到文档中。
<audio>、<canvas>、<embed>、<iframe>、<img>、MathML <math>、<object>、<picture>、SVG <svg>、<video>
5.2.7 交互内容
交互内容是专门用于用户交互的内容。
<a>(如果存在 href 属性)、<audio>(如果存在 controls 属性)、<button>、<details>、<embed>、<iframe>、<img>(如果存在 usemap 属性)、<input>(如果 type 属性不处于隐藏(Hidden)状态)、<label>、<select>、<textarea>、<video>(如果存在 controls 属性)
5.2.8 可感知内容
可感知内容包含非空文本节点或能产生实际渲染输出的后代元素,且该内容可被用户代理以视觉、听觉或触觉形式呈现。
<a>、<abbr>、<address>、<article>、<aside>、<audio>(如果存在 controls 属性)、<b>、<bdi>、<bdo>、<blockquote>、<button>、<canvas>、<cite>、<code>、<data>、<del>、<details>、<dfn>、<div>、<dl>(如果元素的子节点包含至少一个名称-值组)、<em>、<embed>、<fieldset>、<figure>、<footer>、<form>、<h1>、<h2>、<h3>、<h4>、<h5>、<h6>、<header>、<hgroup>、<i>、<iframe>、<img>、<input>(如果 type 属性不处于隐藏状态)、<ins>、<kbd>、<label>、<main>、<map>、<mark>、MathML <math>、<menu>(如果元素的子节点包含至少一个 li 元素)、<meter>、<nav>、<object>、<ol>(如果元素的子节点包含至少一个 li 元素)、<output>、<p>、<picture>、<pre>、<progress>、<q>、<ruby>、<s>、<samp>、<search>、<section>、<select>、<small>、<span>、<strong>、<sub>、<sup>、SVG <svg>、表格、<textarea>、<time>、<u>、<ul>(如果元素的子节点包含至少一个 li 元素)、<var>、<video>、自主自定义元素、不属于元素间空白符的文本
5.2.9 脚本支持元素
脚本支持元素本身不表示任何内容(即不会被渲染),而是用于支持脚本,例如为用户提供功能。
<script>、<template>
5.2.10 select 元素内部内容元素
select 元素内部内容元素是指允许作为 select 元素后代的元素。
<option>、<optgroup>、<hr>、脚本支持元素、<noscript>、<div>
5.2.11 optgroup 元素内部内容元素
optgroup 元素内部内容元素是指允许作为 optgroup 元素后代的元素。
<option>、脚本支持元素、<noscript>、<div>
5.2.12 option 元素内部内容元素
option 元素内部内容元素是指允许作为 option 元素后代的元素。
<div>、不属于以下排除列表的短语内容
以下内容被排除在 option 元素内部内容元素之外:
<datalist>、<object>、交互内容、指定了 tabindex 属性的元素
5.3 透明内容模型
透明内容模型指元素的内容模型继承其父元素的内容模型,而非由自身定义。
5.3.1 典型案例
html
<!-- 放在段落中:只能包含短语内容 -->
<p>
这是一段文字,包含<a href="#">一个链接</a>。
</p>
<!-- 放在分区中:可以包含流内容 -->
<section>
<a href="#">
<h2>标题</h2>
<p>段落</p>
</a>
</section>
5.3.2 常见元素
| 元素 | 说明 |
|---|---|
<a> |
超链接 |
<ins> |
插入标记 |
<del> |
删除标记 |
<map> |
图像映射容器 |
<object> |
外部资源容器 |
<video> |
视频容器 |
<audio> |
音频容器 |
<canvas> |
脚本可绘制区域 |
<slot> |
影子 DOM 插槽 |
六、HTML 注释:容易被忽视的细节
6.1 基本语法
html
<!-- 这是单行注释 -->
<!--
这是多行注释
可用于详细说明代码结构
-->
6.2 使用场景
1. 代码结构与区域标记
这是最常见的用途,用于在复杂的 HTML 结构中划分功能区域,提升可读性和可维护性。
html
<!-- Header Section -->
<header>...</header>
<!-- Main Content -->
<main>...</main>
<!-- Footer Section -->
<footer>...</footer>
2. 临时禁用代码(调试/测试)
快速注释掉不需要的代码而不删除,方便 A/B 测试或问题排查。
html
<!-- 暂时隐藏该模块
<div class="promo-banner">...</div>
-->
3. 模板引擎/服务器端指令占位
在 JSP、PHP、Django、Vue、Angular 等模板中,注释常与服务器端逻辑结合:
html
<!-- 条件渲染:仅管理员可见 -->
<!-- <% if (user.isAdmin) { %> -->
<div class="admin-panel">...</div>
<!-- <% } %> -->
4. 条件注释(IE 兼容性)
历史上用于针对旧版 IE 浏览器提供特定样式或脚本(现代项目已较少使用):
html
<!--[if IE 8]>
<link rel="stylesheet" href="ie8-fix.css">
<![endif]-->
5. 开发协作与说明
为团队成员留下上下文说明,解释特殊实现或待办事项:
html
<!-- TODO: 移动端适配待优化 -->
<!-- NOTE: 此 ID 用于 JS 锚点定位,勿删 -->
<section id="anchor-point">...</section>
6.3 注意事项
1. 绝不放入敏感信息
HTML 注释会原封不动发送到客户端,任何人都能在浏览器中查看。
html
<!-- 错误示例:严重安全隐患 -->
<!-- 数据库密码: db_pass_123 -->
<!-- API密钥: sk_live_abc123 -->
<!-- 内部服务器地址: http://192.168.1.100:8080 -->
正确做法:敏感信息应放在服务端环境变量或配置文件中。
2. 控制注释体积
虽然单个注释影响微小,但大量或冗长注释会增加页面体积:
html
<!-- 避免:几百行的遗留代码注释或开发说明 -->
<!--
这个组件是2023年3月开发的,
当时的需求是...(此处省略500字)
修改历史:v1.0... v1.1... v1.2...
-->
建议 :开发文档应放在独立的 README.md 或内部 Wiki,而非 HTML 中。
3. 避免与业务逻辑耦合
不要依赖 HTML 注释实现功能,它们只是辅助性标记:
html
<!-- 不推荐:JS 读取注释内容来判断逻辑 -->
<!-- data-flag="show-modal" -->
<div>...</div>
正确做法 :使用 data-* 属性或专门的配置对象。
4. 条件注释已废弃
针对 IE 的条件注释在现代浏览器中已失效:
html
<!-- 已废弃,不再生效 -->
<!--[if IE]>
<script src="ie-polyfill.js"></script>
<![endif]-->
现代替代方案:使用 CSS 特性查询或 JS 检测。
5. 团队协作规范
统一注释风格,提升可维护性:
| 场景 | 推荐格式 |
|---|---|
| 区域划分 | <!-- Section: Header --> |
| 待办事项 | <!-- TODO: 移动端适配 --> |
| 重要警告 | <!-- WARNING: 勿删,影响 JS 选择器 --> |
| 临时禁用 | <!-- TEMP: 隐藏促销模块,节后恢复 --> |
现代工程化建议
在 Webpack/Vite 等构建流程中,建议配置自动清理 HTML 注释:
js
// vite.config.js
export default {
build: {
minify: 'terser',
terserOptions: {
format: {
comments: false, // 去除所有注释
},
},
},
}
例外保留:可通过特定标记保留必要注释(如法律声明):
html
<!-- @preserve 版权所有 2026 Company Inc. -->