# AfterPack Pro

Free 对整个 bundle 进行统一保护。Pro 让你只在真正重要的地方施加最强保护：用指令作用于某一个函数或文件。它还会记录每一次构建。

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

Free 是基线：完整的变换目录，统一应用于你的整个 bundle，在你自己的机器上运行，完全免费。当一次许可证校验、一段计价逻辑或一个内嵌凭据的价值远高于周围其余代码时，Pro 就是为这种不均匀的 bundle 准备的。

Pro 改变的是保护落在哪里、精度有多高，而不改变任何单个变换本身的强度。两个层级都可以把 [`complexity`](https://www.afterpack.dev/zh/docs/config#complexity) 拉到你的体积预算所能承受的最高值。

## Free 已经给你的能力

这不是一个有上限的试用版。Free 运行完整流水线：[`complexity`](https://www.afterpack.dev/zh/docs/config#complexity) 没有上限，[阶梯上的](https://www.afterpack.dev/zh/docs/presets)每一档预设都可以使用。

- **每一档预设**：`minify`（目标 0）、`light`（5）、`medium`（7）、`hard`（12）、`extreme`（25），以及你自行设置的任意数值目标。默认是 `light`。
- **每一种变换。** 字面量下沉、控制流扁平化、不透明谓词、混合布尔运算、整数表达式字节码、常量具象化、作用域加深、跨依赖纠缠。
- **每次构建都是全新结构。** 不设置 [seed](https://www.afterpack.dev/zh/docs/config#seed) 即可让每次构建都抽取新的种子；需要可复现输出时再固定它。
- **你能想到的其他一切**：[Protection Map](https://www.afterpack.dev/zh/docs/protection-map)、[source map](https://www.afterpack.dev/zh/docs/config#sourceMap-enabled)、[框架插件](https://www.afterpack.dev/zh/docs/frameworks)、[框架检测](https://www.afterpack.dev/zh/docs/config#reflection-allow)。混淆本身不需要账户、不需要 key、不需要任何网络请求。
- **默认对调试友好。** Devtools、断点、`console.log` 和监视表达式都能照常使用。当构建报告了什么问题时，参见[诊断](https://www.afterpack.dev/zh/docs/diagnostics)。

输出体积随预设增长；实测体积见[性能](https://www.afterpack.dev/zh/docs/performance#output-size)。Pro 让你只在值得的地方花费这些体积，而不必为整个 bundle 都提高预设。

*(build targets diagram — see the web page)*

## Pro 买到的东西

### 可以瞄准目标的保护

在 Free 上，你的配置会平等地应用到 bundle 中的每一个节点。在 Pro 上，一段[标记区域](https://www.afterpack.dev/zh/docs/directives#what-you-can-set)可以覆盖你的全局设置。

实际上这意味着你可以把 bundle 整体留在 [`light`](https://www.afterpack.dev/zh/docs/presets)，以获得更快的构建和更小的体积，同时仍然在真正重要的那二十行代码上使用 `extreme`：

```js
/* @afterpack preset=hard */
function verifyLicense(token) {
  // raised to complexity target 12, string floor forced on
}
/* @afterpack end */

/* @afterpack skip */
function debugPanel() {
  // target 0, floor off — left alone
}
/* @afterpack end */
```

区域来自 `@afterpack` [块注释](https://www.afterpack.dev/zh/docs/directives#writing-one)。指令由插件从你的源码中读取。

[指令可以设置什么](https://www.afterpack.dev/zh/docs/directives#what-you-can-set)：任何按区域生效的选项。

> **指令如何传达给引擎**
>
> 负责读取的插件是 [`@afterpack/next`](https://www.afterpack.dev/zh/docs/frameworks/nextjs)、[`@afterpack/vite`](https://www.afterpack.dev/zh/docs/frameworks/vite)、[`@afterpack/webpack`](https://www.afterpack.dev/zh/docs/frameworks/webpack)，或[其余框架](https://www.afterpack.dev/zh/docs/frameworks)。由 [`npx afterpack@latest <path>`](https://www.afterpack.dev/zh/docs/cli#usage) 驱动的 Pro 构建会在整个 bundle 上获得 Pro 保护，但没有[区域](https://www.afterpack.dev/zh/docs/directives)：CLI 运行在已构建的输出上，那里的注释已经不存在，因此它不读取指令，并会拒绝 [`directives.enabled`](https://www.afterpack.dev/zh/docs/config#directives-enabled)。

### 针对许可证和支付路径的加固

两项 Free 构建不会应用的保护，你可以开启：

| 设置 | 它为你做了什么 |
|---|---|
| [`transforms.selfIntegrity.enabled`](https://www.afterpack.dev/zh/docs/config#transforms-kind-enabled) | 对它自身的校验表加一道检查，只检测对这张表的修改。对你代码其他地方的修改不会被检测到。未被改动时，它不会改变任何东西。 |
| [`transforms.comparisonHardening.enabled`](https://www.afterpack.dev/zh/docs/config#transforms-kind-enabled) | 一次字符串相等性判断会变成单向摘要校验，因此你用来比较的字面量会从产物中完全消失。 |

两者默认都是关闭的。确认一个被标记的反射模式，在两个层级上的做法相同：在你的配置中使用 [`reflection.allow`](https://www.afterpack.dev/zh/docs/config#reflection-allow)。它不能通过指令设置。

### 构建运行在 AfterPack 的基础设施上

一个 [`key`](https://www.afterpack.dev/zh/docs/config#key) 会把你构建中的文件路由到 [AfterPack 的云端](https://www.afterpack.dev/zh/docs/deployment-modes)，每个文件处理完成后即返回受保护的输出。不需要额外安装什么，也不需要维护更新。

源码在内存中处理，不会被持久化保存。引擎所在位置发生变化时会有什么不同，参见[部署模式](https://www.afterpack.dev/zh/docs/deployment-modes)。

### 每一次构建的记录

云端构建都会被记录下来。AfterPack 会保存该次构建的 [Protection Map](https://www.afterpack.dev/zh/docs/protection-map) 以及一行汇总指标，这样[控制台](https://www.afterpack.dev/zh/docs/dashboard/builds)就能展示任意最近构建的地图、[诊断信息](https://www.afterpack.dev/zh/docs/diagnostics)和耗时。这样无需重新运行任何东西，就能回答“这次发布到底有没有被保护？”这个问题。[存储按项目进行，也可以关闭](https://www.afterpack.dev/zh/docs/protection-map#turning-it-off)。保留期为一年**且**每个项目最多保留最近 500 次构建，以先到期者为准。用量按兆字节计量。参见 [Pro 如何收费](https://www.afterpack.dev/zh/docs/pro#what-pro-costs)。

按层级划分的完整能力矩阵，参见[套餐与层级](https://www.afterpack.dev/zh/docs/tiers)。

## Pro 如何收费

Pro 计量的是用量，而不是席位。你购买的是**[云端引擎](https://www.afterpack.dev/zh/docs/deployment-modes)处理的 JavaScript 的 MB 数**：不是构建次数，不是文件数，也不是请求数。包括 Free 在内，每个层级的工作区成员数都没有上限。

一个 Pro key 会把你整个客户端 bundle 都路由经过云端引擎，它处理的每一个字节都会被计量，包括标记区域之外的代码。一个 1.5 MB 的 Next.js 客户端 bundle，每次构建都会消耗月度配额中的 1.5 MB。

获取 Pro 额度有三种方式：

- **注册即可免费获得：每月 10 MB，无需绑卡。** 足够在真实 bundle 上使用这些精准功能并比较输出结果。参见[账户](https://www.afterpack.dev/zh/docs/accounts)。
- **Extra MB：一次性 $5 购买 20 MB。** 永不过期，不会自动续费，购买它也不会开启订阅。每隔几周才发布一次的项目，仅靠充值就足够运行。
- **当用量足够大、订阅更划算时，可选择起价 $49/月 的套餐。** Indie 每月包含 500 MB，Team 为 3 GB，Studio 为 8 GB，每档都支持按 MB 自动计费的超额用量，避免繁忙的迭代周期让 CI 失败。Indie 和 Team 都包含 14 天试用。

一次构建按**先用套餐配额、再用 Extra MB、最后才计超额**的顺序扣减，所以充值额度排在月度配额之后，而不会被优先消耗。价格、项目数量上限、超额费率和消费上限都在[套餐与层级](https://www.afterpack.dev/zh/docs/tiers)中。

作为参考，一个典型的生产环境 SPA bundle 大小在几百 KB 到一两 MB 之间。免费的 10 MB 能覆盖好几次真实构建，Indie 的 500 MB 能覆盖几百次。

## 即将推出

目前尚不可用。以下是[公开路线图](https://www.afterpack.dev/zh/roadmap)上的 Pro 相关项目，AfterPack 在那里说明即将推出的内容，但不给出具体日期。

| 能力 | 它会带来什么 |
|---|---|
| **跨模块混淆** | 跨越模块边界而不仅是在单个文件内进行纠缠。 |
| **网络传输伪装** | 为你的 API 请求和响应生成逐次构建的编解码器，作用于网络传输层。 |
| **托管 source map** | 通过经过身份验证的查询还原生产环境的堆栈跟踪，而 map 本身永远不会发布出去。 |

## Pro 专属设置在 Free 构建上会怎样

遇到会提高保护强度的[按区域指令](https://www.afterpack.dev/zh/docs/directives#free-builds)时，Free 构建会直接终止，而不会用比源码要求更弱的保护继续下去，并会忽略其他任何指令。上面两项加固设置则完全不会被应用。无法连接到云端的 Pro 构建会[失败即中止](https://www.afterpack.dev/zh/docs/diagnostics#fail-closed-no-exceptions)。

## 下一步

- [部署模式](https://www.afterpack.dev/zh/docs/deployment-modes)：每个层级在哪里执行，以及失败即中止在实践中意味着什么。
- [Cloud API 参考](https://www.afterpack.dev/zh/docs/cloud-api)：每一次 Pro 构建背后的线上协议。
- [层级](https://www.afterpack.dev/zh/docs/tiers)：价格、MB 额度，以及各个套餐分别适合什么场景。
- [Protection Map](https://www.afterpack.dev/zh/docs/protection-map)：一次构建的地图展示了什么，以及它存储在哪里。[打开实时演示](https://www.afterpack.dev/protection-map-demo)。
- [指令](https://www.afterpack.dev/zh/docs/directives)：上面区域标记的完整语法。
- [配置](https://www.afterpack.dev/zh/docs/config)：所有的 key、flag、变量和指令，汇总在一处。
- [控制台中的构建](https://www.afterpack.dev/zh/docs/dashboard/builds)：一次被记录的云端构建，事后看起来是什么样子。
