recursal/MDN huggingface dataset:
<del>
=====

HTML 的 **`<del>`** 标签表示一些被从文档中删除的文字内容。比如可以在需要显示修改记录或者源代码差异的情况使用这个标签。`<ins>`标签的作用恰恰于此相反：表示文档中添加的内容。

这个标签通常（但不一定要）在文字上显示删除线。

|  |  |
| --- | --- |
| 内容分类 | 短语元素 或者 流式元素 。 |
| 允许的内容 | 透明内容模型 |
| 标签省略 | 不允许，开始标签和结束标签都不能省略。 |
| 允许的父元素 | 任意短语元素 |
| 允许的 ARIA 角色 | 任意 |
| DOM 接口 | `HTMLModElement` (en-US) |

属性
--

这个标签包含全局属性。

`cite`

提供一个 URI，其中的资源解释作出修改的原因（比如：根据某次会议讨论）。

`datetime`

这个属性说明修改的时间和日期，这里的时间和日期格式要符合规范。如果设置的值不符合该规范，那么它将没有任何意义。

示例
--


```html
<p><del>This text has been deleted</del>, here is the rest of the paragraph.</p>
<del><p>This paragraph has been deleted.</p></del>
```

### 结果

~~This text has been deleted~~, here is the rest of the paragraph.

~~This paragraph has been deleted.~~

规范
--

| Specification |
| --- |
| HTML Standard # the-del-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

相关链接
----

* `<ins>` 标签用来表示插入文本的内容
* `
` 标签用来显示删除线，代表内容被删除了
<rp>
====

**HTML `<rp>` 元素**用于为那些不能使用 `<ruby>` 元素展示 ruby 注解的浏览器，提供随后的圆括号。

|  |  |
| --- | --- |
| Content categories | 无 |
| 允许的内容 | 文本 |
| 标签省略 | 不允许，开始标签和结束标签都不能省略。 |
| 允许的父元素 | `<ruby>` 元素。 `<rp>` 必须位于 `<rt>` 的前面和后面。 |
| 允许的 ARIA 角色 | 任意 |
| DOM 接口 | `HTMLElement` |

属性
--

这个元素仅仅支持 全局属性 (en-US)。

用法注解
----

* Ruby 注解用于展示东亚文字的发音，例如使用日语罗马音和汉语拼音的文字。 `<rp>` 元素用于不支持 `<ruby>` 元素的情况。 `<rp>` 的内容提供了应该展示的东西，通常是圆括号，以便表示 ruby 注解的存在。
示例
--


```html
<ruby>
  漢 <rp>(</rp><rt>han</rt><rp>)</rp> 字 <rp>(</rp><rt>zi</rt><rp>)</rp>
</ruby>
```

规范
--

| Specification |
| --- |
| HTML Standard # the-rp-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `<ruby>`
* `<rt>`
* `<rb>`
* `<rtc>`
<param>
=======

**已弃用:** 不再推荐使用该特性。虽然一些浏览器仍然支持它，但也许已从相关的 web 标准中移除，也许正准备移除或出于兼容性而保留。请尽量不要使用该特性，并更新现有的代码；参见本页面底部的兼容性表格以指导你作出决定。请注意，该特性随时可能无法正常工作。

概要
--

\*\*HTML `<param>元素`\*\*为`<object>`元素定义参数

|  |  |
| --- | --- |
| 内容分类 (en-US) | 无 |
| 允许内容 | 不允许，它是一个空元素（empty element）。 |
| 标签省略 | 由于它是一个 void 元素，所以开始标签必须出现，而结束标签必须不出现。 |
| 允许的父级元素 | 任何以下内容（flow content (en-US)）都可以在`<object>`元素的前面作为它的父元素。 |
| DOM 接口 | `HTMLParamElement` (en-US) |

属性
--

这个元素包含 全局属性 (en-US).

`name`

参数的名字。

`type` 
已弃用

仅当 valuetype 设置为“ref”时才使用。根据 URI 中给定的数据确定 MIME 类型。

`value`

确定参数的值。

`valuetype` 
已弃用

确定参数的类型。可选值如下：

* data: 默认值。该值作为字符串变量传递给对象实例。
* ref: 该值是存储运行时变量的资源的 URI。
* object: 同一页面（document）中另一个`<object>`的 ID。

示例
--

请在`<object>`页面中查看<param>的示例。

规范
--

| Specification |
| --- |
| HTML Standard # the-param-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参阅
--

* `<object>`
<wbr>
=====

**HTML `<wbr>` 元素** — 一个文本中的位置，其中浏览器可以选择来换行，虽然它的换行规则可能不会在这里换行。

|  |  |
| --- | --- |
| Content categories (en-US) | Flow content (en-US), phrasing content (en-US). |
| Permitted content | Empty |
| Tag omission | It is an empty element; it must have a start tag, but must not have an end tag. |
| Permitted parents | Any element that accepts phrasing content (en-US). |
| Permitted ARIA roles | Any |
| DOM interface | `HTMLElement` |

属性
--

这个元素仅仅包含 全局属性 (en-US)

Notes
-----

在 UTF-8 编码的页面中， `<wbr>` 表现为 `U+200B ZERO-WIDTH SPACE` （零宽空格）代码点。特别是，它表现为 Unicode bidi BN 代码点，也就是说，它对 bidi-ordering 没有影响：`<div dir=rtl>123,<wbr>456</div>` 展示 `123,456` 而不是 `456,123`，当不拆成的两行时候。

出于相同原因， `< wbr >`元素不会在换行的地方引入连字符。为了使连字符仅仅在行尾出现，使用连字符软实体 (`& shy;`) 来代替。

这个元素首先在 Internet Explorer 5.5 中实现，并且在 HTML5 中官方定义。

示例
--

*Yahoo 代码规范*推荐在标点之前为 URL 换行，以便避免将标点符号留在行尾，这会让读者将 URL 的末尾搞错。


```html
<p>
  http://this<wbr />.is<wbr />.a<wbr />.really<wbr />.long<wbr />.example<wbr />.com/With<wbr />/deeper<wbr />/level<wbr />/pages<wbr />/deeper<wbr />/level<wbr />/pages<wbr />/deeper<wbr />/level<wbr />/pages<wbr />/deeper<wbr />/level<wbr />/pages<wbr />/deeper<wbr />/level<wbr />/pages
</p>
```

规范
--

| Specification |
| --- |
| HTML Standard # the-wbr-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
<blockquote>：块级引用元素
===================

**HTML `<blockquote>` 元素**（或者 HTML 块级引用元素），代表其中的文字是引用内容。通常在渲染时，这部分的内容会有一定的缩进（注 中说明了如何更改）。若引文来源于网络，则可以将原内容的出处 URL 地址设置到 cite 特性上，若要以文本的形式告知读者引文的出处时，可以通过 `<cite>` 元素。

尝试一下
----

|  |  |
| --- | --- |
| Content categories (en-US) | Flow content (en-US), sectioning root, palpable content. |
| Permitted content | Flow content (en-US). |
| Tag omission | 不允许，开始标签和结束标签都不能省略。 |
| Permitted parents | Any element that accepts flow content (en-US). |
| Permitted ARIA roles | Any |
| DOM interface | `HTMLQuoteElement` (en-US) |

属性
--

此元素的属性包含 全局属性。

`cite`

是一个标注引用的信息的来源文档或者相关信息的 URL。通常用来描述能够解释引文的上下文或者引用的信息。

使用说明
----

若要修改被引用内容的缩进距离，可以使用 CSS `margin-left` 和/或 `margin-right` 属性，或使用 `margin` 缩写属性。

若想使用在行内引用较短的内容而非创建一个单独的引用块，可使用 `<q>`（Quotation）元素。

如果想要使用短引用（行间引用），可以使用`<q>` 标签。

示例
--

下面的这个例子演示了使用 `<blockquote>` 元素引用一段来自 RFC 1149 的内容，以禽类作为载体的 IP 数据包传输标准。


```html
<blockquote cite="https://tools.ietf.org/html/rfc1149">
  <p>
    Avian carriers can provide high delay, low throughput, and low altitude
    service. The connection topology is limited to a single point-to-point path
    for each carrier, used with standard carriers, but many carriers can be used
    without significant interference with each other, outside of early spring.
    This is because of the 3D ether space available to the carriers, in contrast
    to the 1D ether used by IEEE802.3. The carriers have an intrinsic collision
    avoidance system, which increases availability.
  </p>
</blockquote>
```


上面的 HTML 代码将会生成：

规范
--

| Specification |
| --- |
| HTML Standard # the-blockquote-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 适用于行内引用的 `<q>` 元素。
* 适用于来源引文的 `<cite>` 元素。
<dd>
====

**HTML `<dd>` 元素**（*HTML 描述元素*）用来指明一个描述列表 (`<dl>`) 元素中一个术语的描述。这个元素只能作为描述列表元素的子元素出现，并且必须跟着一个 `<dt>` 元素。

|  |  |
| --- | --- |
| 内容分类 (en-US) | None |
| 允许的内容 | 流内容 (en-US) |
| 标签省略 | 必须有开标签。如果该元素后面紧跟着另一个 <dd> 元素，或者父元素中没有更多内容，则可以省略闭标签。 |
| 允许的父元素 | 该元素需要出现在 `<dt>` 元素和 `<dd>` 元素之后，并且在一个 `<dl>` 元素里。 |
| DOM 接口 | `HTMLElement` |

属性
--

该元素包含全局属性 (en-US)。

`nowrap` 
非标准

如果这个属性的值为 yes，那么定义的描述文字将不会包裹。默认值为 no。

示例
--

示例请看<dl> 的示例。

规范
--

| Specification |
| --- |
| HTML Standard # the-dd-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `<dl>`, `<dt>`
<rt>
====

**HTML Ruby 文本 (`<rt>`) 元素**包含字符的发音，字符在 ruby 注解中出现，它用于描述东亚字符的发音。这个元素始终在 `<ruby>` 元素中使用。

|  |  |
| --- | --- |
| 内容分类 | 无 |
| 允许的内容 | 短语内容 |
| 标签省略 | 如果 `<rt>` 元素紧紧跟随 `<rt>` 或者 `<rp>` 元素，或者父元素中没有更多内容了，结束标签可以省略。 |
| 允许的父元素 | `<ruby>` 元素 |
| 允许的 ARIA 角色 | 任意 |
| DOM 接口 | `HTMLElement` |

属性
--

该元素仅仅包含 全局属性 (en-US)。

示例
--


```html
<ruby> 汉 <rt>Hàn</rt> 字 <rt>Zì</rt> </ruby>
```

规范
--

| Specification |
| --- |
| HTML Standard # the-rt-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `<ruby>`
* `<rp>`
* `<rb>`
* `<rtc>`
<article>
=========

**HTML `<article>`** 元素表示文档、页面、应用或网站中的独立结构，其意在成为可独立分配的或可复用的结构，如在发布中，它可能是论坛帖子、杂志或新闻文章、博客、用户提交的评论、交互式组件，或者其他独立的内容项目。

尝试一下
----

给定文档中可以包含多篇文章;例如，阅读器在博客上滚动时一个接一个地显示每篇文章的文本，每个帖子将包含在`<article>`元素中，可能包含一个或多个`<section>`。

|  |  |
| --- | --- |
| 内容分类 (en-US) | Flow content (en-US), sectioning content, palpable content. |
| 允许的内容 | Flow content (en-US). |
| 标记省略 | 不允许，开始标签和结束标签都不能省略。 |
| 允许的父元素 | 所有接受 Flow content (en-US)的元素。注意`<article>`元素不能成为`<address>`元素的子元素。 |
| 允许的 ARIA roles | `application` (en-US), `document` (en-US), `feed` (en-US), `main` (en-US), `presentation` (en-US), `region` (en-US) |
| DOM 实例 | `HTMLElement` |

属性
--

此元素只具有全局属性 (en-US)。

使用说明
----

* 每个`<article>`，通常包括标题（<h1> - <h6>元素）作为`<article>`元素的子元素。
* 当`<article>`元素嵌套使用时，则该元素代表与外层元素有关的文章。例如，代表博客评论的`<article>`元素可嵌套在代表博客文章的`<article>`元素中。
* `<article>`元素的作者信息可通过`<address>`元素提供，但是不适用于嵌套的`<article>`元素。
* `<article>`元素的发布日期和时间可通过`<time>`元素的`pubdate`属性表示。
* 可以使用`<time>` 元素的`datetime`属性来描述`<article>`元素的发布日期和时间。请注意`<time>`的\*`pubdate`\* 属性不再是\*W3C (en-US)\* \*HTML5\*标准。
示例
--


```html
<article class="film\_review">
  <header>
    <h2>Jurassic Park</h2>
  </header>
  <section class="main\_review">
    <p>Dinos were great!</p>
  </section>
  <section class="user\_reviews">
    <article class="user\_review">
      <p>Way too scary for me.</p>
      <footer>
        <p>
          Posted on
          <time datetime="2015-05-16 19:00">May 16</time>
          by Lisa.
        </p>
      </footer>
    </article>
    <article class="user\_review">
      <p>I agree, dinos are my favorite.</p>
      <footer>
        <p>
          Posted on
          <time datetime="2015-05-17 19:00">May 17</time>
          by Tom.
        </p>
      </footer>
    </article>
  </section>
  <footer>
    <p>
      Posted on
      <time datetime="2015-05-15 19:00">May 15</time>
      by Staff.
    </p>
  </footer>
</article>
```

规范
--

| Specification |
| --- |
| HTML Standard # the-article-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

相关文章
----

* Others section-related elements: `<body>`, `<nav>`, `<section>`, `<aside>`, `<h1>` (en-US), `<h2>` (en-US), `<h3>` (en-US), `<h4>` (en-US), `<h5>` (en-US), `<h6>` (en-US), `<hgroup>`, `<header>`, `<footer>`, `<address>`
* Sections and outlines of an HTML5 document.
<slot>
======

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

* Learn more
* See full compatibility
* Report feedback

**备注：** 本翻译的一些术语参考了Vuejs-中文页面。

**HTML `<slot>` 元素**，作为 Web Component 技术套件的一部分，是 Web 组件内的一个占位符。该占位符可以在后期使用自己的标记语言填充，这样你就可以创建单独的 DOM 树，并将它与其他的组件组合在一起。

|  |  |
| --- | --- |
| Content categories | Flow content, phrasing content |
| Permitted content | Transparent |
| Events | `slotchange` (en-US) |
| Tag omission | 不允许，开始标签和结束标签都不能省略。 |
| Permitted parents | Any element that accepts phrasing content |
| Permitted ARIA roles | None |
| DOM interface | `HTMLSlotElement` |

属性
--

此元素有全局属性。

`name`

插槽的名字。拥有 name 属性的插槽叫**具名插槽**。

示例
--


```html
<template id="element-details-template">
  <style>
 details {
 font-family: "Open Sans Light", Helvetica, Arial, sans-serif;
 }
 .name {
 font-weight: bold;
 color: #217ac0;
 font-size: 120%;
 }
 h4 {
 margin: 10px 0 -8px 0;
 background: #217ac0;
 color: white;
 padding: 2px 6px;
 border: 1px solid #cee9f9;
 border-radius: 4px;
 }
 .attributes {
 margin-left: 22px;
 font-size: 90%;
 }
 .attributes p {
 margin-left: 16px;
 font-style: italic;
 }
 </style>
  <details>
    <summary>
      <code class="name"
 >&lt;<slot name="element-name">NEED NAME</slot>&gt;</code
 >
      <i class="desc"><slot name="description">NEED DESCRIPTION</slot></i>
    </summary>
    <div class="attributes">
      <h4>Attributes</h4>
      <slot name="attributes"><p>None</p></slot>
    </div>
  </details>
  <hr />
</template>
```


**备注：** 你可以在 element-details (see it running live) 找到这个示例的完整演示版。另外，你也可以在Using templates and slots这里找到具体的解释。

规范
--

| Specification |
| --- |
| HTML Standard # the-slot-element |
| DOM Standard # shadow-tree-slots |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
theme-color
===========

`<meta>` 中 `name` 属性的值为 **`theme-color`** 时，用户的浏览器将根据所设定的建议颜色来改变用户界面。倘若设置了该值，则 `content` 属性必须包含有效的 CSS `<color>` 值。

示例
--


```html
<meta name="theme-color" content="#4285f4" />
```


下图展示了上方所示的 `<meta>` 元素对于 Android 端 Chrome 浏览器造成的影响。

![示 theme-color 对浏览器的影响](/zh-CN/docs/Web/HTML/Element/meta/name/theme-color/theme-color.png)

*图片来源：《图标和浏览器颜色》, 由 Google 创作并经署名 4.0 国际 (CC BY 4.0) 许可证共享。*

你可以用 `media` 来查询一个媒体类型，如果条件符合则使用对应颜色。比如：


```html
<meta
 name="theme-color"
 media="(prefers-color-scheme: light)"
 content="white" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />
```

规范
--

| Specification |
| --- |
| HTML Standard # meta-theme-color |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
<input type="reset">
====================

**`reset`** 类型的 `<input>` 元素将渲染为按钮，且带有默认的 `click` 事件，用于将表单中的所有输入重置为其初始值。

尝试一下
----

**备注：** 你应该尽量避免在表单中包含重置按钮。它们很少具有实用性，事实上更有可能使用户因误点而感到沮丧（通常是在尝试单击提交按钮时）。


|  |  |
| --- | --- |
| **值** | 用做按钮标签的字符串 |
| **事件** | `click` |
| **支持的常用属性** | `type` 和 `value` |
| **IDL 属性** | `value` |
| **DOM 接口** | `HTMLInputElement` |
| **方法** | 无 |

值
-

`<input type="reset">` 元素的 `value` 属性包含一个用做按钮标签的字符串，诸如 `reset` 之类的按钮没有其他值。

### 设置 value 属性


```html
<input type="reset" value="Reset the form" />
```

### 省略 value 属性

如果你未指定 `value`，则会获得一个带有默认标签的按钮（通常为“重置”，但这将根据用户代理而有所不同）：


```html
<input type="reset" />
```

使用重置按钮
------

`<input type="reset">` 按钮用于重置表单。如果要创建自定义按钮，并使用 JavaScript 自定义行为，你需要使用 `<input type="button">`，或者最好使用 ``<button>`` 元素。

### 一个简单的重置按钮

我们将从创建一个简单的重置按钮开始：


```html
<form>
  <div>
    <label for="example">Type in some sample text</label>
    <input id="example" type="text" />
  </div>
  <div>
    <input type="reset" value="Reset the form" />
  </div>
</form>
```


上述代码会渲染成这样：

尝试在文本字段中输入一些文本，然后点击重置按钮。

### 添加重置键盘快捷键

像对 `<input>` 元素所做的那样，向重置按钮添加一个快捷键是非常有意义的，且可以通过 `accesskey` 全局属性来实现。

在这个例子中， `r` 被指定为访问键（需要按下 `r` 键与浏览器或操作系统的特定键相组合；关于这些命令的详细列表请参见 `accesskey`）。


```html
<form>
  <div>
    <label for="example">Type in some sample text</label>
    <input id="example" type="text" />
  </div>
  <div>
    <input type="reset" value="Reset the form" accesskey="r" />
  </div>
</form>
```


上面的示例的问题在于，用户无法知道访问键是什么！事实上，是因为修饰符通常是非标准的，以避免与系统和软件快捷键冲突。在构建网站时，请确保以不干扰网站设计的方式提供此信息（例如，通过提供易于访问的链接来指向有关网站访问键的信息）。向按钮添加提示（也可以使用 `title` 属性），尽管这并不是出于无障碍目的的完善的解决方案。

### 禁用和启用重置按钮

要禁用重置按钮，只需在其上指定 `disabled` 全局属性，如下所示：


```html
<input type="reset" value="Disabled" disabled />
```


你可以在运行时通过简单地将 `disable` 设置为 `true` 或 `false` 来启用和禁用按钮。在 JavaScript 中，使用 `btn.disabled = true` 或 `btn.disabled = false`。

**备注：** 有关启用和禁用按钮的更多概念，请参见 `<input type="button">` 页面。

验证
--

按钮并不参与约束性验证，它们并没有实际的约束价值。

示例
--

我们在上面已经提供了一些简单的示例。实际上关于重置按钮并没有更多的内容了。

规范
--

| Specification |
| --- |
| HTML Standard # reset-button-state-(type=reset) |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<input>` 和 `HTMLInputElement` 实现接口
* 表单和按钮
* HTML 表单
* `<button>` 元素
* 表单控件 CSS 兼容性列表
使用 dns-prefetch
===============

**`DNS-prefetch`** 尝试在请求资源之前解析域名。这可能是后面要加载的文件，也可能是用户尝试打开的链接目标。

为什么要使用 dns-prefetch？
--------------------

当浏览器从（第三方）服务器请求资源时，必须先将该跨源域名解析为 IP 地址，然后浏览器才能发出请求。此过程称为 DNS 解析。虽然 DNS 缓存可以帮助减少此延迟，但 DNS 解析可能会给请求增加明显的延迟。对于打开了与许多第三方的连接的网站，此延迟可能会大大降低加载性能。

`dns-prefetch` 可帮助开发人员掩盖 DNS 解析延迟。HTML `<link>` 元素通过设置 `rel` 属性值为 `dns-prefetch` 提供此功能。然后在 href 属性中指明要跨源的域名：

语法
--


```html
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
```

示例
--


```html
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
    <!-- 其他 head 元素 -->
  </head>
  <body>
    <!-- 你的页面内容 -->
  </body>
</html>
```


每当站点引用跨源资源时，都应在 `<head>` 元素中放置 `dns-prefetch` 提示，但是要记住一些注意事项。

最佳实践
----

请记住以下三点：

**首先**，`dns-prefetch` 仅对跨源域上的 DNS 查找有效，因此请避免使用它来指向你的站点或域。这是因为，到浏览器看到提示时，你的站点背后的 IP 已经被解析了。

**其次**，还可以通过使用 HTTP Link 字段将 `dns-prefetch`（以及其他资源提示）指定为 HTTP 标头之一：


```http
Link: <https://fonts.googleapis.com/>; rel=dns-prefetch
```


**再其次**，考虑将 `dns-prefetch` 与 `preconnect` 提示配对。`dns-prefetch` 只执行 DNS 查询，而 `preconnect` 则是建立与服务器的连接。这个过程包括 DNS 解析，以及建立 TCP 连接，如果是 HTTPS 网站，就进一步执行 TLS 握手。将这两者结合起来，可以进一步减少跨源请求的感知延迟。你可以像这样安全地将它们结合起来使用：


```html
<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin />
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
```


**备注：** 如果页面需要建立与许多第三方域的连接，则将它们预先连接会适得其反。`preconnect` 提示最好仅用于最关键的连接。对于其他的连接，只需使用 `<link rel="dns-prefetch">` 即可节省第一步——DNS 查询——的时间。

配对这些提示的逻辑是因为对 dns-prefetch 的支持比对预连接的支持要好。不支持预连接的浏览器仍然可以通过回退到 dns-prefetch 来获得更多好处。由于这是 HTML 特性，因此容错性很强。如果不支持的浏览器遇到 dns-prefetch 提示（或任何其他资源提示），则网站不会中断，只是不会获得它提供的好处。

一些资源（如字体）以匿名模式加载。在这种情况下，应使用预连接提示设置 crossorigin 属性。如果省略了它，则浏览器将仅执行 DNS 查找。

参见
--

* <link>
* HTML 属性：rel
* crossorigin
* 跨源资源共享（CORS）
* HTTP 标头
* HTTP 标头 Link
优化启动性能
======

一个在软件应用开发中经常被忽视的方面—即便在那些专注于性能优化的软件中—就是启动时的表现。你的应用需要花费多长时间启动？当应用加载时是否会卡住用户的设备或浏览器？这会让用户担心你的应用崩溃了，或者哪儿出错了。花时间确保你的应用能够更好地启动总是一个好主意。这篇文章提供了一些技巧和建议来帮助你达成这个目标，不管是在写一个新的应用还是从其他平台向 Web 移植一个应用。

更好地启动
-----

不论在什么平台上，尽可能**快**地启动总是一个好主意。因为这是个很宽泛的问题，在这里我们不会着重关注。相反我们会关注构建 Web 应用时更重要的一个问题：尽可能**异步地**启动。这意味着不要将你所有的启动代码在应用主线程中的唯一一个事件处理函数中运行。

相反，你应该这样写你的代码，让你的应用在后台线程创建一个 Web worker ，做尽可能多的工作（比如，获取和处理数据）。然后，所有必须在主线程中完成的事情（比如用户事件和渲染用户界面）应该被分成小的片段，这样，当应用启动时，应用的事件循环就可以持续地运行下去。这可以避免应用、浏览器以及/或者设备出现锁死。

为什么异步性很重要？除了上面提出的原因，还考虑了无响应页面或用户界面的影响。如果用户错误地启动了应用，将不能取消。如果应用正在浏览器中运行，用户可能会收到一个“应用无响应”或“加载缓慢”的提醒。你应该显示几种界面，比如进度条，这样用户可以在应用启动时知道他们需要等待多长时间。

如果有这样的打算
--------

如果你从头开始你的项目，通常很容易把所有的东西都写成“正确的方式”，使得代码片段具有合适的异步性。所有纯粹在启动时的计算应该在后台线程中执行，同时使主线程事件的运行时间尽可能缩短。应包含进度指示器，以便用户知道发生了什么以及他们将要等待多久。从理论上来说，无论如何，设计新的应用程序并能很好地启动应该很容易。

但是，另一方面，当你将现有应用程序移植到 Web 上时，问题会变得棘手。桌面应用程序不需要以异步方式编写，因为通常操作系统会为你处理该问题；或者应用程序当前是唯一正在运行的主要任务，而这具体取决于操作环境。源程序可能有一个主循环，可以被轻松地改成异步操作（通过分别运行每个主循环）；启动通常只是一个持续的整体过程，过程中可能会定期更新进度表。

虽然你可以使用 Web workers 异步运行体积巨大，持续时间长的 JavaScript 代码块，但还是要给出一个重大警告：workers 不具备访问 WebGL 或音频的能力，亦不能向主线程发送同步消息，所以你甚至不能将这些 API 代理到主线程中。所有的这一切意味着，除非你够轻松地抽取启动过程中的“纯计算”代码块，加入到 workers 中，否则你最后还是得在主线程上运行大部分或全部的启动代码。

但是即便是那样的代码，通过一点点工作，也可以变为异步的。

异步化
---

关于如何构建你的启动过程，使得其尽可能异步执行，这里有些建议。（不论是新应用还是移植的）：

* 启动时，在需要异步执行的脚本标签上使用 `defer` 或 `async` 属性。这会允许 HTML 解析器更高效地处理文档。 Async scripts for asm.js 中有更多关于这方面的信息。
* 如果你需要解码资源文件（比如，解码 JPEG 文件并将其转换为原始纹理数据，以便随后在 WebGL 中使用），最好在 workers 里做这件事。
* 当处理浏览器支持的数据格式时（例如，解析图像数据），使用设备或浏览器内置的解码器而不是运行你自己的或者使用 or using one from the original codebase。预先提供的那个基本上一定会快得多，并且能够减小你的应用的启动体积。另外，浏览器可以自动并行化这些解码器的工作。
* 所有能并行的数据处理都应该并行化。不要一团接一团地处理数据，如果可能的话，同时处理它们！
* 在你启动的 HTML 文件中，不要包含不会在关键路径下出现的脚本或样式表。只在需要时加载他们。
* 不要强迫 Web 引擎构建不需要的 DOM，一种简单的“hack”的方式是把你的 HTML 留在文档里，但是在外层包裹注释。

```html
<div id="foo">
  <!--
 <div> ...
 -->
</div>
```

* 当文档的一部分需要被渲染时，加载被注释的 HTML
```

foo.innerHTML = foo.firstChild.nodeValue;
```


你能通过异步的方式做的事越多，应用就能更好的利用多核处理器。

### 移植问题

一旦初始加载完成，应用的主程序开始运行，有可能你的应用一定会是单线程的，尤其当它是个移植的程序时。尝试改善主程序的启动过程时，最重要的事情是将代码重构为小片段。这些小片段可以在你应用的主循环中通过多个调用在分散的代码段中执行，这样主线程就能处理输入和类似的事件。

Emscripten 提供了一个 API 帮助处理这种重构；比如你可以用 `emscripten_push_main_loop_blocker()` 创建一个函数，在主线程可以继续运行前执行。通过创建一个可以依序调用的函数队列，你可以更轻松地在不阻塞主线程地情况下管理代码的运行。

但是这留下了不得不重构现有代码，使程序真正这样运行的问题。这可能需要一些时间。

### 我究竟要异步化到什么程度？

最好记住大多数浏览器，在你的代码阻塞主线程太长时间——大约 10 秒左右的时候，就会开始抱怨。理想情况下，你不会在任何地方阻塞那么长时间，但是只要你把时间保持在这之下，就不会有问题。不过要记住，如果有人有个比你更旧更慢的电脑，他们或许会比你经历更长的等待！

其他建议
----

除了异步化之外，还有一些其他的事情，可以帮助你改善应用启动时间。这是其中的一部分：

下载时间

一定要记住用户需要花多少时间下载你游戏的数据。如果你的游戏非常大，很受欢迎，或者需要频繁的重下内容，你应该考虑买个速度越快越好托管服务器。你还应该考虑压缩数据，尽可能缩小其体积。

GPU 因素

编译着色器，以及将纹理传输到 GPU 会占用时间，特别是在比较复杂的游戏中。尽管这也会发生在本地 (非 Web ) 游戏中，但还是会很恼人。不要不告诉用户游戏实际上还在启动中就这么做。

数据大小

尽力优化游戏数据的体积，小一些的文件下载和处理都比大文件快。

主观因素

你可以在启动过程中做一些事情来使用户专注于其上，这会让时间看起来过得更快些。就游戏而言，可以考虑播放一些背景音乐或者显示漂亮的启动画面；在运算执行期间，更新你的进度提示，改变显示内容，或者做任何你想做的事情：这有助于用户知晓应用正在做一些工作，而不是一声不吭地呆在那儿。

参见
--

* Apps
* Games
懒加载
===

**延迟加载**（懒加载）是一种将资源标识为非阻塞（非关键）资源并仅在需要时加载它们的策略。这是一种缩短关键渲染路径长度的方法，可以缩短页面加载时间。

延迟加载可以在应用程序的不同时刻发生，但通常会在某些用户交互（例如滚动和导航）上发生。

概览
--

随着网络的发展，发送给用户的资源数量和规模都在急剧增加。从 2011 年到 2019 年，桌面端的资源中位数从 **~100KB** 增至 **~400KB**，移动端的资源中位数从 **~50KB** 增至 **~350KB**。桌面端上图片资源的大小已经从 **~250KB** 增至 **~900KB**，而移动设备上的图片 **~100KB** 增至 **~850KB**。

解决这个问题的方法之一是延迟加载对第一次渲染并不重要的资源来缩短关键渲染路径的长度。一个实际例子是，当用户打开一个电商网站的主页时，该页面有一个指向购物车页面/区域的链接，并且**只有**在用户导航到购物车页面/区域时才会下载其所有资源（如 JavaScript、CSS 和图片）。

策略
--

延迟加载可以通过多种策略应用于多个资源。

### 常规

#### 代码拆分

JavaScript、CSS 和 HTML 可以被分割成较小的代码块。这样就可以在前期发送所需的最小代码，改善页面加载时间。其余的可以按需加载。

* 入口点分离：通过应用的入口点分离代码
* 动态分离：通过动态 import() 语句分离代码
### JavaScript

#### 脚本类型模块

任何类型为 `type="module"` 的脚本标签都被视为一个 JavaScript 模块，并且默认情况下会被延迟。

### CSS

默认情况下，CSS 被视为渲染阻塞资源，因此，在 CSSOM 构造完成之前，浏览器不会渲染任何已处理的内容。CSS 必须尽量小，才能尽快送达，建议使用媒体类型和查询实现非阻塞渲染。


```html
<link href="style.css" rel="stylesheet" media="all" />
<link href="portrait.css" rel="stylesheet" media="(orientation:portrait)" />
<link href="print.css" rel="stylesheet" media="print" />
```


可以执行一些 CSS 优化来实现这一目标。

### 字体

默认情况下，字体请求会延迟到构造渲染树之前，这可能会导致文本渲染延迟。

可以使用 `<link rel="preload">`、CSS font-display 属性和字体加载 API 来覆盖默认行为并预加载网络字体资源。

参见 Link 元素。

### 图片和 iframe

很多时候，网页包含许多图片，这些图片会影响数据的使用和网页的加载速度。这些图片大部分都在屏幕之外（非关键），需要用户互动，如滚动，才能看到它们。

#### Loading 属性

`<img>` 元素上的 `loading` 属性（或 `<iframe>` 上的 `loading` 属性）可用于指示浏览器推迟加载屏幕外的图像/iframe，直到用户滚动到其附近。


```html
<img src="image.jpg" alt="..." loading="lazy" />
<iframe src="video-player.html" title="..." loading="lazy"></iframe>
```


当早期加载的内容全部加载完毕时，`load` 事件就会触发；这时，完全有可能（甚至有可能）在可视视口 (en-US)范围内有一些延迟加载的图片还没有加载。

你可以通过检查其布尔属性 `complete` (en-US) 的值来确定某个图片是否已经完成加载。

#### Polyfill

包含这个 polyfill，以提供对旧的和目前不兼容的浏览器的支持：loading-attribute-polyfill。

#### Intersection Observer API

Intersection Observer 允许用户得知被观察的元素何时进入或退出浏览器的视口。

#### 事件处理器

当浏览器的兼容性至关重要时，有以下几种选择：

* polyfill intersection observer
* 回退到滚动、调整大小或方向变化事件处理器，以确定特定元素是否在视口中
规范
--

| Specification |
| --- |
| HTML Standard # lazy-loading-attributes |

参见
--

* 渲染阻塞 CSS
* 使用延迟加载来提高加载速度
关键渲染路径
======

**关键渲染路径**是浏览器将 HTML，CSS 和 JavaScript 转换为屏幕上的像素所经历的步骤序列。优化关键渲染路径可提高渲染性能。关键渲染路径包含了 文档对象模型(DOM)，CSS 对象模型 (CSSOM)，渲染树和布局。

在解析 HTML 时会创建文档对象模型。HTML 可以请求 JavaScript，而 JavaScript 反过来，又可以更改 DOM。HTML 包含或请求样式，依次来构建 CSS 对象模型。浏览器引擎将两者结合起来以创建渲染树。布局确定页面上所有内容的大小和位置。确定布局后，将像素绘制到屏幕上。

优化关键渲染路径可以缩短首次渲染的时间。了解和优化关键渲染路径对于确保重排和重绘可以每秒 60 帧的速度进行，以确保高效的用户交互并避免卡顿是很重要的。

理解 CRP
------

Web 性能包含了服务器请求和响应、加载、执行脚本、渲染、布局和绘制每个像素到屏幕上。

网页请求从 HTML 文件请求开始。服务器返回 HTML——响应头和数据。然后浏览器开始解析 HTML，转换收到的数据为 DOM 树。浏览器每次发现外部资源就初始化请求，无论是样式、脚本或者嵌入的图片引用。有时请求会阻塞，这意味着解析剩下的 HTML 会被终止直到重要的资源被处理。浏览器接着解析 HTML，发请求和构造 DOM 直到文件结尾，这时开始构造 CSS 对象模型。等到 DOM 和 CSSOM 完成之后，浏览器构造渲染树，计算所有可见内容的样式。一旦渲染树完成布局开始，定义所有渲染树元素的位置和大小。完成之后，页面被渲染完成，或者说是绘制到屏幕上。

### 文档对象模型

DOM 构建是增量的。HTML 响应变成令牌（token），令牌变成节点，而节点又变成 DOM 树。单个 DOM 节点以 startTag 令牌开始，以 endTag 令牌结束。节点包含有关 HTML 元素的所有相关信息。该信息是使用令牌描述的。节点根据令牌层次结构连接到 DOM 树中。如果另一组 startTag 和 endTag 令牌位于一组 startTag 和 endTag 之间，则你在节点内有一个节点，这就是我们定义 DOM 树层次结构的方式。

节点数量越多，关键渲染路径中的后续事件将花费的时间就越长。测一下吧！几个额外的节点不会有什么区别，但“DIV 癖”（divitis）可能会导致问题。

### CSS 对象模型

DOM 包含页面所有的内容。CSSOM 包含了页面所有的样式，也就是如何展示 DOM 的信息。CSSOM 跟 DOM 很像，但是不同。DOM 构造是增量的，CSSOM 却不是。CSS 是渲染阻塞的：浏览器会阻塞页面渲染直到它接收和执行了所有的 CSS。CSS 是渲染阻塞是因为规则可以被覆盖，所以内容不能被渲染直到 CSSOM 的完成。

CSS 有其自身的规则集合用来定义标识。注意 CSS 中的 C 代表的是“层叠”。CSS 规则是级联的。随着解析器转换标识为节点，节点的后代继承了样式。像处理 HTML 那样的增量处理功能没有被应用到 CSS 上，因为后续规则可能被之前的所覆盖。CSS 对象模型随着 CSS 的解析而被构建，但是直到完成都不能被用来构建渲染树，因为样式将会被之后的解析所覆盖而不应该被渲染到屏幕上。

从选择器性能的角度，更少的特定选择器是比更多的要快。例如，`.foo {}` 是比 `.bar .foo {}` 更快的因为当浏览器发现 `.foo` ，接下来必须沿着 DOM 向上走来检查 `.foo` 是不是有一个祖先 `.bar`。越是具体的标签浏览器就需要更多的工作，但这样的弊端未必值得优化。

如果你测量过解析 CSS 的时间，你将会被浏览器实在地快所震惊。更具体的规则更昂贵因为它必须遍历更多的 DOM 树节点，但这所带来的额外的消耗通常很小。先测量一下。然后按需优化。特定化或许不是你的低垂的果实。在 CSS 中选择器的性能优化，提升仅仅是毫秒级的。有其他一些方式来优化 CSS，例如压缩和使用媒体查询来异步处理 CSS 为非阻塞的请求。

### 渲染树

渲染树包括了内容和样式：DOM 和 CSSOM 树结合为渲染树。为了构造渲染树，浏览器检查每个节点，从 DOM 树的根节点开始，并且决定哪些 CSS 规则被添加。

渲染树只包含了可见内容。头部（通常）不包含任何可见信息，因此不会被包含在渲染树中。如果有元素上有 `display: none;`，它本身和其后代都不会出现在渲染树中。

### 布局

一旦渲染树被构建，布局变成了可能。布局取决于屏幕的尺寸。布局这个步骤决定了在哪里和如何在页面上放置元素，决定了每个元素的宽和高，以及他们之间的相关性。

什么是一个元素的宽？块级元素，根据定义，默认有父级宽度的 100%。一个宽度 50% 的元素，将占据父级宽度的一半。除非另外定义，body 有 100% 的宽，意味着它占据视窗的 100%。设备的宽度影响布局。

视窗的元标签定义了布局视窗的宽度，从而影响布局。没有的话，浏览器使用视窗的默认宽度，默认全屏浏览器通常是 960px。在默认情况下像你的手机浏览器的全屏浏览器，通过设置 `<meta name="viewport" content="width=device-width">`，宽度将会是设备的宽度而不是默认的视窗宽度。设备宽度当用户在横向和纵向模式旋转他们的手机时将会改变。布局发生在每次设备旋转或浏览器缩放时。

布局性能受 DOM 影响——节点数越多，布局就需要更长的时间。布局将会变成瓶颈，如果期间需要滚动或者其他动画将会导致迟滞。20ms 的延迟在加载或者方向改变时或许还可以接受，但在动画或滚动时就会迟滞。任何渲染树改变的时候，像添加节点、改变内容或者在一个节点更新盒模型样式的时候布局就会发生。

为了减小布局事件的频率和时长，批量更新或者避免改动盒模型属性。

### 绘制

最后一步是将像素绘制在屏幕上。一旦渲染树创建并且布局完成，像素就可以被绘制在屏幕上。加载时，整个屏幕被绘制出来。之后，只有受影响的屏幕区域会被重绘，浏览器被优化为只重绘需要绘制的最小区域。绘制时间取决于何种类型的更新被附加在渲染树上。绘制是一个非常快的过程，所以聚焦在提升性能时这大概不是最有效的部分，重点要记住的是当测量一个动画帧需要的时间需要考虑到布局和重绘时间。添加到节点的样式会增加渲染时间，但是移除样式增加的 0.001ms 或许不能让你的优化物有所值。记住先测量。然后你可决定它的优化优先级。

优化 CRP
------

提升页面加载速度需要通过被加载资源的优先级、控制它们加载的顺序和减小这些资源的体积。性能提示包含 1）通过异步、延迟加载或者消除非关键资源来减少关键资源的请求数量，2）优化必须的请求数量和每个请求的文件体积，3）通过区分关键资源的优先级来优化被加载关键资源的顺序，来缩短关键路径长度。