# 按区域生效的混淆指令

写在源码中的注释，用于改变 AfterPack 对其所标记代码的保护。

Source: https://www.afterpack.dev/zh/docs/directives

指令是一条注释，用于改变 AfterPack 对其所标记代码的保护。构建中的其余部分沿用你为整个程序设置的[配置](https://www.afterpack.dev/zh/docs/config)。指令是 [Pro](https://www.afterpack.dev/zh/docs/pro) 功能。

## 如何编写

指令是以 `@afterpack` 开头的块注释。单独占一行时，它作用于从这里直到对应的 `/* @afterpack end */` 之间的所有代码。若同一行后面紧跟代码，它只作用于该行余下的部分。

```js
/* @afterpack preset=hard */
function checkLicense(token) {
  return verifySignature(token, PUBLIC_KEY);
}
/* @afterpack end */

const apiKey = /* @afterpack preset=extreme */ "YOUR_SECRET";
```

键名是[配置](https://www.afterpack.dev/zh/docs/config)页面中的点分名称，多个键以空格分隔：`/* @afterpack preset=hard inflation.max=6 */`。布尔键单独出现即表示 `true`。指令只作用于它所包裹的代码：从中调用的函数不受影响，导入也不受影响。

## 可以设置的选项

任何按区域生效的选项。每个选项都链接到它的定义，那里的 `directive` 标签页给出了准确的写法。

- [`skip`](https://www.afterpack.dev/docs/config#skip) — directive only
- [`preset`](https://www.afterpack.dev/docs/config#preset)
- [`complexity`](https://www.afterpack.dev/docs/config#complexity)
- [`inflation.max`](https://www.afterpack.dev/docs/config#inflation-max)
- [`strings.encode`](https://www.afterpack.dev/docs/config#strings-encode)

指令中的其他选项会被忽略，并作为信息级别报告。未知的键或格式错误的指令会报错。

## 何时使用

- 用 `preset=extreme` 标记最关键的代码，例如许可证校验、防篡改逻辑或打包进来的密钥。程序的其余部分保持更轻、更小。
- 用 `skip` 或更低的 `preset` 标记必须保持可读或高性能的代码，例如热循环或第三方代码片段。

## 应该标记什么

| 资产 | 指令 | 原因 |
| --- | --- | --- |
| 许可证 / 授权校验 | [`preset=hard`](https://www.afterpack.dev/zh/docs/config#preset) | 只要改动一个比特，你的软件就会被破解。请搭配 [`transforms.comparisonHardening.enabled`](https://www.afterpack.dev/zh/docs/best-practices#the-two-anti-tamper-transforms) 使用。 |
| 支付校验器 | `preset=hard` | 威胁在于篡改，而不只是读取。 |
| 反作弊 / 反机器人逻辑 | `preset=hard` 或 `preset=extreme` | 提高作弊手段的开发成本并拖慢其迭代节奏。对手有时间也有动机，因此请搭配以服务端为权威的校验。 |
| 无法移到服务端的硬编码密钥 | 在字面量之前内联写入 [`/* @afterpack preset=extreme */`](https://www.afterpack.dev/zh/docs/config#preset) | 最好是彻底移除，但总有一些会漏进来。`preset=extreme` 让恢复它的代价变得高昂，但该字面量仍然存在于输出中。若代码需要与某个字面量做比较，可以用 [`transforms.comparisonHardening.enabled`](https://www.afterpack.dev/zh/docs/config#transforms-kind-enabled) 让它完全不出现在输出中。对于已经发布出去的密钥，请参阅[如果你不小心发布了密钥](https://www.afterpack.dev/zh/docs/best-practices#if-you-shipped-a-secret-by-accident)。 |
| 专有算法（定价、路由、ML 胶水代码） | 在核心函数周围包上 `/* @afterpack preset=extreme */ … /* @afterpack end */` | 这是你最有价值的代码。复杂度目标设为最高，并开启常量下限。 |

在能覆盖该资产的最小范围内应用指令。给一个 500 行的文件整体标记 `preset=extreme`，会让整个打包产物膨胀，收益却很小。

## 检查实际应用了什么

[Protection Map](https://www.afterpack.dev/zh/docs/protection-map) 会显示每一个由指令产生的区域，以及区域内实际应用了哪些处理。已被读取但没有产生任何效果的指令，会出现在构建的[诊断](https://www.afterpack.dev/zh/docs/diagnostics)中。

## Free 构建

本地构建对整个程序应用同一份配置。会提高保护强度的指令会让构建停止，并报错要求提供 Pro 密钥（[`DIAG_PRO_DIRECTIVE_REQUIRES_KEY`](https://www.afterpack.dev/zh/docs/diagnostics#complete-reference)）：高于程序预设的 `preset`、高于程序目标或位于 `light` 程序中的非零 `complexity`、高于程序预算的 `inflation.max`，或者在程序的字符串 floor 关闭时设置 `strings.encode=on`。其他任何指令都会被忽略，其区域沿用整个程序的配置，包括 `skip`、更低的 `preset` 或 `complexity`、更低的 `inflation.max`，以及变换掩码（`transforms.only`、`transforms.deny`、`controlFlow.enabled=off`）。[CLI](https://www.afterpack.dev/zh/docs/cli) 在两个层级上都完全不读取指令。
