# 控制台中的构建

每一次 Pro Cloud 构建的逐构建记录：覆盖率、膨胀率、复杂度、构建耗时、花费、诊断信息，以及 Protection Map。

Source: https://www.afterpack.dev/zh/docs/dashboard/builds

每一次 [**Pro Cloud**](https://www.afterpack.dev/zh/docs/deployment-modes) 构建都会留下一条记录：它何时运行、来自哪个提交、花费了多少、引擎能对其中多少内容进行变换，以及引擎在处理过程中报告了什么。Free 本地构建从不联系 AfterPack，所以它们永远不会出现在这里。

## 构建列表

一个项目的所有构建，最新的排在最前面。

| 列 | 含义 |
| --- | --- |
| **构建时间** | 构建运行的时间。 |
| **提交** | AfterPack 为这次构建检测到的 git SHA（参见 [`seed`](https://www.afterpack.dev/zh/docs/config#seed)），以短格式显示、复制时为完整值，用于把这一行和某次部署对应起来。 |
| **文件** | 这次构建发送给 AfterPack 的输出文件，不包括其中包含的源文件。 |
| **输出** | 经过保护后发布出去的内容。 |
| **计费量** | AfterPack 处理的输入字节数。这是你被收费的依据。 |
| **构建耗时** | AfterPack 为构建增加的时间，在边缘测量；较早的构建没有这项记录，所以这些行显示为缺失，而不是 `0`。 |
| **覆盖率** | 在收到的输出中，引擎可以自由变换的部分所占的比例。 |
| [**膨胀率**](https://www.afterpack.dev/zh/docs/config#inflation-max) | 输出 ÷ 输入。这是保护让你的用户在下载上付出的代价。 |

列表显示该项目最近的构建。查看某次构建时，侧边栏会把该项目相邻的构建嵌套在**构建**下方，让你一键就能对比两次构建。

## 单次构建的完整信息

打开一行，页头会显示提交（没有 git 上下文时显示构建 id）以及**查看 Protection Map** 按钮；没有可打开的内容时，则显示一个*未保存地图*标签。

### 结果

四个数字，每一个回答一个不同的问题。

- **覆盖率**：在收到的输出中，引擎可以自由变换的部分所占的比例。
- **膨胀率**：输出 ÷ 输入的体积，也就是你的用户要为之付出代价的那个数字。一定程度的增长是意料之中的，因为让代码难以阅读的变换会占用空间。
- **复杂度**：在可处理的字节上达到的平均复杂度，与这次构建的[目标](https://www.afterpack.dev/zh/docs/config#complexity)对照显示（`score / target`）。复杂度仅供参考，并不衡量安全性。
- **体积**：输入了多少，发布了多少。

### 覆盖构成

输入的每一个字节都去了哪里。各个区段加起来等于输入，它们的占比与上面的覆盖率一致。

| 区段 | 含义 |
| --- | --- |
| **可处理** | 引擎可以自由变换的字节。 |
| **安全保留** | 引擎无法触及的字节，因为它无法安全地表示这些结构。 |
| **反射保留** | 因为你的代码使用了[运行时反射](https://www.afterpack.dev/zh/docs/config#reflection-allow)而被保留的字节。 |
| **你已排除** | 与你的 [`paths.exclude`](https://www.afterpack.dev/zh/docs/config#paths-exclude) 设置匹配的文件，在解析之前就被跳过，并原样返回。 |
| **你已跳过** | 你标记了 [`/* @afterpack skip */`](https://www.afterpack.dev/zh/docs/config#skip) 的区域。 |
| **未计入** | 不属于任何其他区段的输入字节。 |

与各区段并列的还有：**薄弱点**（输出中仍可读的源码字符串，不计属性名；打开地图查看位置）和**[指令](https://www.afterpack.dev/zh/docs/directives)**（引擎在你的源码中找到的 `@afterpack` 标记，记录在这里，这也是你[确认某条指令已被识别](https://www.afterpack.dev/zh/docs/directives#checking-what-was-applied)的方式）。

### 源文件

构建中每个源文件的矩形树图，按输入的字节数确定大小，按引擎处理到的程度着色：灰色图块表示没有可处理的内容，红色图块表示出了问题，从橙色到绿色表示从弱到强。图块只涵盖能追溯到某个文件的输出，约为你发布内容的一半，因此单个图块的膨胀率并不是整个构建的膨胀率。其余部分是 AfterPack 每个 bundle 注入一次的[运行时](https://www.afterpack.dev/zh/docs/config#inflation-max)。共享的运行时代码没有对应的图块，这就是为什么整个构建的膨胀会比任何单个文件都大。

这一行仅对[付费套餐](https://www.afterpack.dev/zh/docs/tiers)开放：Free 工作区看到的是锁定状态而不是矩形树图，不过构建页面上的其他每一行都是免费的。

### 输出文件采集

这里告诉你构建的输出文件中有多少可以在已存储的地图中查看，以及其余文件发生了什么；它不衡量保护，因为无论是否被采集，每个文件都已经被混淆。一个例外：如果构建触及了 [AfterPack 的时间预算](https://www.afterpack.dev/zh/docs/cloud-api)，它会停止开始处理新文件，剩余的每个文件都会失败。重新运行构建，或者把它拆分成更小的构建。

### 耗时

构建在 AfterPack 边缘花费的时间，包括等待响应下载完成的时间。其中很大一部分来自 [Protection Map](https://www.afterpack.dev/zh/docs/protection-map)：生成并返回它会增加混淆时间，所以在[项目设置](https://www.afterpack.dev/zh/docs/dashboard/workspaces)中关闭采集可以省下这部分时间。

### 计费

这次构建从你的工作区中扣除了什么：**计量**（被计费的输入字节数），以及它的来源：**配额**、**Extra MB**、**超额**。

### 诊断信息

引擎在混淆这次构建时报告的内容，按稳定的代码分组并附带计数；因为这是你自己工作区中你自己的构建，你还能看到每一条的消息和文件。信息级别的条目是意料之中的，所以只有错误和严重级别的条目会被高亮显示。

页面会说明发生的是以下三种情况中的哪一种：记录了条目；构建是干净的，没有报告任何内容；或者 AfterPack 根本没有任何记录，这正是 Free 构建留下的情况。

每个代码都是稳定的，可以在 bug 报告中引用。参见[诊断](https://www.afterpack.dev/zh/docs/diagnostics)。

## Protection Map

当采集开启且构建存储了一份地图时，**查看 Protection Map** 会打开[逐词元视图](https://www.afterpack.dev/zh/docs/protection-map)：你的原始源码，按每个词元的复杂度分数着色，并显示你所选代码的[还原类](https://www.afterpack.dev/zh/docs/reversal-classes)。存储的地图内嵌你的原始源码，工作区中的每个人都能读取；保留期和按项目的开关见[隐私与数据处理](https://www.afterpack.dev/zh/docs/privacy#protection-maps-for-cloud-builds-are-stored-and-you-can-turn-that-off)，本页会注明这次构建确切的保留截止日期。没有存储地图的构建会改为说明原因：采集被关闭、它不是 Pro Cloud 构建，或者它没有携带可用于生成地图的输入 source map。

## 趋势

项目概览以自适应的时间粒度绘制覆盖率、膨胀率和构建耗时随时间的变化，并显示与上一周或上一月相比的差值；工作区概览则对所有项目的用量做同样的展示。

## 下一步

- [Protection Map](https://www.afterpack.dev/zh/docs/protection-map)：阅读这份产物本身。
- [还原类](https://www.afterpack.dev/zh/docs/reversal-classes)：类别标签的含义。
- [诊断](https://www.afterpack.dev/zh/docs/diagnostics)：引擎发出的代码。
- [构建与 CI](https://www.afterpack.dev/zh/docs/builds)：首先如何产出这些构建。
- [用量与计费](https://www.afterpack.dev/zh/docs/dashboard/usage)：计量的字节都去了哪里。
