# 发布 AfterPack：一款面向 Web 的免费 JavaScript 混淆器

AfterPack 是免费的 JavaScript 混淆器，每次构建都会把你的代码改写成不同的样子，在 Cloudflare Worker 里每次请求也是如此。

Source: https://www.afterpack.dev/zh/blog/announcing-afterpack-javascript-obfuscator

Published: 2026-09-28 · Author: Nikita Savchenko · Tags: announcement, javascript obfuscation, security, AI

今天，我们要发布三样东西：

- **[AfterPack](https://www.afterpack.dev/docs/quickstart)**，一款面向 AI 时代的现代 JavaScript 混淆器。它把你的生产构建每次都变成一个不同的程序：每次构建都是新的样子，在 Cloudflare Worker 里，每次请求也是新的样子。
- **全新升级的[网站扫描器](https://www.afterpack.dev/security-scanner)**，能找出任何网站代码里可读的部分：公开的 source map、可读的逻辑和泄露的凭据。
- **[在线 playground](https://www.afterpack.dev/playground)**，直接在浏览器里，用你自己的代码试试 AfterPack。

AfterPack（afterpack.dev）是一款 JavaScript 混淆器，支持任何框架。CLI 和插件是开源的，本地引擎免费，Pro 云端构建每月 49 美元起。构建之后运行 `npx afterpack@latest` 即可开始，或者让你的编码 Agent 帮你添加它。

Watch the launch video (0:52): https://www.youtube.com/watch?v=uHmXIW8v3wk

认识一下 AfterPack：一个免费的构建工具，它让你发布出去的代码对扫描器和人都读不懂，也让 AI 追不上。每次构建都是完全不同的代码，所以针对某一个版本写的补丁脚本——外挂、用户脚本、绕过手段——都套不进下一个版本。一个针对你代码写出来的工具，本就该在你下一个版本失效；现在，在你自己的 Cloudflare Worker 里，它甚至能在下一次请求就失效。

## AI 都能读懂 JavaScript 了，为什么还要混淆？

因为 AI 能读懂的东西，它也能重写、重新打包。把编码 Agent 指向你的 bundle，几分钟后，有人手里就拿到了你的定价规则、付费墙校验或反机器人逻辑的干净、可编辑源码，还附带一个能打补丁或绕过它们的脚本。这以前是专家才干得了的活；现在只是一句提示词。而且只要你的代码结构不变，这个补丁就能一直用下去。压缩从来没有把这些代码藏起来：所谓的 [Claude Code「泄露」](https://www.afterpack.dev/blog/claude-code-source-leak)，其实就是一个自发布起就躺在 npm 上、本来就可读的 bundle。压缩后的 bundle 仍会泄露什么、如何检查你自己的网站，见[用户能在你的 JavaScript 里看到什么，以及如何保护它](https://www.afterpack.dev/blog/protect-javascript-source-code)。

2026 年 5 月，我把两款流行混淆器的旗舰演示交给 Claude Code，只配了一份四段话的提示词。[Claude Opus 4.6 把它还原成了干净源码](https://www.afterpack.dev/blog/ai-deobfuscates-javascript)，用了 10 分钟；Claude Opus 4.7 用了 20 分钟。那只是小演示，不是完整应用，而且这些模型如今已经落后当前一代。

你的定价规则、许可证校验、反欺诈规则和未发布的功能，一直都在 bundle 里。变的是谁能读懂它们，以及读得有多快。你还能控制的，是建立在这些解读之上的工具能用多久。

## 混淆后的 JavaScript 能被还原吗？

_2026 年 10 月编辑：本回答的早期版本引用过一个百分比，说一次构建的反混淆成果有多少还能用在下一次构建上。那个数字测的东西比这句话说的要窄，所以已经删掉；现在的回答只写实际测到的结果。_

能。只要时间足够，任何混淆器的输出都能被还原，AfterPack 的也不例外。每次构建的形态都不同，所以针对某次构建的模式编写的工具，到下一次构建就会失效。运行你代码的人仍然能读到它用到的值：在我们自己的测量中，一个 15 行的运行时钩子在我们测试的每一次构建上都还原出了 97 个字符串中的 96 个（[实测结果](https://www.afterpack.dev/docs/threat-model#measured-results)）。

已经被读懂的逻辑也不会因此被忘掉：如果有人已经弄明白了你的折扣规则，新的一次构建并不能让他忘记。

能过期的，是建立在这次阅读之上的工具。剥掉许可证校验的脚本、绕过付费墙的补丁、从每个版本里抽取你评分规则的提取器：每一个都是针对某一次构建的结构写出来的。最流行的开源混淆器输出的形态是固定的，免费的公开反混淆器里就内置了针对这些形态的硬编码识别器，所以工具写一次，就能在之后每一次构建上继续用。

AfterPack 每次构建都从一个新的随机种子开始。标识符名称、编码后的字符串、解码器的签名、状态编号和被掩码的常量，全都会变，所以工具会硬编码的那些细节每次都不一样。把引擎放进 Worker 里运行，这个窗口就从一个版本缩短到一次请求。

## AfterPack 里有什么？

一个 CLI、适配你已在使用的打包工具的插件、供 Workers 使用的 WebAssembly 版本、Pro 云端构建、一份展示每次构建保护了什么的报告，以及一个免费的网站扫描器。

| 项目 | AfterPack |
| --- | --- |
| 是什么 | 面向生产构建的 JavaScript 混淆器：它改写的是打包工具的产物，而不是你的源文件 |
| 引擎 | Rust，由 CLI 和插件在本地运行，或以 WebAssembly 形式（[`@afterpack/wasm`](https://www.afterpack.dev/docs/workers)）在你自己的 Worker 里运行 |
| 输出 | CLI 和插件默认每次构建都不同；只有需要字节完全一致时才固定[种子](https://www.afterpack.dev/docs/builds) |
| 许可证 | CLI 和插件采用 Apache-2.0；引擎依据 AfterPack Engine License 免费使用 |
| 价格 | 本地引擎免费；Pro 每月 49 美元起（[套餐](https://www.afterpack.dev/docs/tiers)） |
| 开始使用 | 构建后运行 `npx afterpack@latest`，或使用[框架插件](https://www.afterpack.dev/docs/frameworks) |

表格里没写到的：

- **框架插件**，支持 Next.js、Vite、webpack、Astro、Nuxt、SvelteKit、Svelte、Vue、Angular、Parcel、esbuild、Rollup 和 Electron。你平常的生产构建会直接输出混淆后的代码。
- **[Pro](https://www.afterpack.dev/docs/pro)**：传入密钥，同样的调用就会在 AfterPack 的云端运行，并支持用[指令](https://www.afterpack.dev/docs/directives)把更重的保护集中到关键代码上。如果密钥或云端不可用，构建会直接失败，而不是悄悄发出保护更弱的代码。
- **[Protection Map](https://www.afterpack.dev/docs/protection-map)**：一份 HTML 报告，展示你的原始源码，每个 token 都按它经过的变换量着色。它会在你的构建生成 source map 时写出；插件可以帮你打开这一选项。
- **免费的[安全扫描器](https://www.afterpack.dev/security-scanner)**，也可以通过 `npx afterpack audit <url>` 使用。

## AfterPack 混淆后的输出长什么样？

标识符会消失，字符串字面量会被编码在一个运行时解码器后面；再往上加多少东西，取决于预设。[`light`](https://www.afterpack.dev/docs/presets)（默认）会编码字符串并改写语法，不添加任何结构层——这是大多数项目合适的基线。`medium` 会让生产代码明显更难跟踪；`hard` 面向定价、权限判断、许可证校验这类重要代码；`extreme` 设定各预设中最高的复杂度，最适合只针对一个函数或一个文件，而不是整个 bundle。

一个 139 字节的函数，混淆前：

```js
export function discount(plan, seats) {
  if (plan === "team" && seats >= 10) return 0.2;
  if (plan === "team") return 0.1;
  return 0;
}
```

混淆后，一次 `npx afterpack@latest`，默认 `light` 预设（2026 年 9 月 27 日）：

```js
export function discount(N, O) {
  if (N === Jr("T|P4") && O >= 10) return 0.2;
  if (N === Jr("T|P4")) return 0.1;
  return 0;
}
```

`"team"` 不见了，换成了一段密文和一次解码器调用；再跑一次，名字、密文和解码器的签名全都会变。在 `light` 下，`10`、`0.2`、`0.1` 这样的数字仍然可读；`medium` 及以上还会把像这个 `10` 一样的整数常量掩码起来。解码器本身也要占一部分体积，所以这么小的文件，混淆后的比例会显得比真实 bundle 大得多：在真实 bundle 上，`light` 的输出按 gzip 计是输入的 1.9 到 2.4 倍（[预设](https://www.afterpack.dev/docs/presets)）。

把你自己的函数粘贴到 [playground](https://www.afterpack.dev/playground) 里，看看每个预设会把它变成什么样——不用安装，也不用注册。

## 现在就试试 AfterPack

- **粘贴代码**：[playground](https://www.afterpack.dev/playground) 会直接在浏览器里混淆你粘贴的任何代码，无需安装。
- **扫描你的网站**：[安全扫描器](https://www.afterpack.dev/security-scanner)会告诉你，你的生产环境 JavaScript 已经暴露了什么。
- **一句提示词**：交给任意编码 Agent——`Add AfterPack to this project: read afterpack.dev/llms.txt, follow the quickstart for my framework, then run a production build and show me the Protection Map.`
- **一条命令**：在下一次构建后运行 `npx afterpack@latest`。

## 在 Cloudflare Worker 里按请求混淆 JavaScript

[`@afterpack/wasm`](https://www.afterpack.dev/docs/workers) 以 WebAssembly 形式在你自己的 Worker 里运行引擎，每次调用都传入一个新种子，每个响应就会是不同方式混淆出来的代码：

```js
import { obfuscate } from "@afterpack/wasm";

export default {
  async fetch(request) {
    const upstream = await fetch("https://example.com/app.js"); // your origin's bundle
    if (!upstream.ok) return upstream;
    const source = await upstream.text();
    const result = await obfuscate(
      { path: "app.js", source },
      { preset: "hard", seed: crypto.randomUUID() },
    );
    return new Response(result.bytes, {
      headers: { "content-type": "application/javascript" },
    });
  },
};
```

如果我们在 Apple M2 Max 上用 Node 跑这个处理函数（2026 年 9 月 27 日），从本地源站提供那个 `discount` 文件：四次请求会得到四份不同的输出，每份都返回正确的折扣。模块预热之后，每次混淆都不到 4 ms；第一次调用要实例化引擎，大约 40 ms。这是一个 139 字节的输入；真实的 bundle 会消耗多得多的 CPU，而且每个响应都要付一次。[Workers 指南](https://www.afterpack.dev/docs/workers)介绍了各套餐的限制，以及什么时候每个轮换窗口缓存一个形态是更划算的选择。

完整的配置，包括 wrangler 配置、按时间窗口缓存一个形态以及真实的 `curl` 输出，见教程[如何用 Cloudflare Workers 对每次请求混淆 JavaScript](https://www.afterpack.dev/blog/obfuscate-javascript-cloudflare-workers)。

## 如何混淆 Next.js、Vite、webpack 或其他任何构建

在构建之后运行 CLI，或者为你的打包工具安装插件，让每次生产构建都输出混淆后的代码。CLI 无需任何配置；构建完成后在项目根目录运行：

```bash
npx afterpack@latest
```

它会找到你的构建产物（`dist/`、`.next/`、`.output/`、`build/` 或 `out/`），原地改写并保留一份备份；`npx afterpack@latest restore` 可以撤销这次运行。

如果想让混淆成为构建本身的一部分，为你的打包工具安装插件：

```bash
npm install -D @afterpack/next   # or @afterpack/vite, @afterpack/webpack
```

每个插件只需要一处很小的配置改动，比如用 `withAfterpack(config)` 包住你的 Next.js 配置；[框架](https://www.afterpack.dev/docs/frameworks)页面给出了从 Astro 到 Parcel 每个受支持打包工具的写法。想知道你的线上网站今天暴露了什么，先用[扫描器](https://www.afterpack.dev/security-scanner)跑一遍。

## AfterPack 有哪些局限？

AfterPack 提高的是读懂你的代码、以及复用针对它的工具的成本；它无法对插桩运行中程序的人隐藏值，所以密钥以及任何授予访问权限的东西，都应该放在你的服务器上。它带来的好处则跟着你本来就在跑的构建一起来：每个版本都是一个新目标，不需要额外记住任何步骤。

## AfterPack 接下来做什么？

接下来是网络层混淆：[network transport cloaking](https://www.afterpack.dev/roadmap) 会让你的 API 请求和响应经过一个随每次构建变化的编解码器。跨模块混淆会把逻辑在模块边界之间连接起来。JavaScript 之后，下一步是 HTML 和 CSS。

## AfterPack 常见问题

### AfterPack 免费吗？

免费。CLI、框架插件和本地引擎都免费，你的源码永远不会离开你的机器。[Pro](https://www.afterpack.dev/docs/pro) 增加云端构建和按区域的[指令](https://www.afterpack.dev/docs/directives)，每月 49 美元起；注册的 Free 工作区每月有 10 MB 的 Pro 构建额度。完整对比见[套餐与层级](https://www.afterpack.dev/docs/tiers)。

### AfterPack 开源吗？

CLI 和框架插件是开源的，采用 Apache-2.0 协议，托管在 [GitHub](https://github.com/afterpack-dev/afterpack) 上。它们运行的引擎依据 AfterPack Engine License 免费使用。

### 混淆会拖慢我的代码吗？

会有一些影响，预设越强影响越大。默认是 `light`。可以为整个项目提高[预设](https://www.afterpack.dev/docs/presets)，也可以用 Pro 指令只把 `hard` 或 `extreme` 用在需要的函数上。

### AfterPack 和其他 JavaScript 混淆器有什么不同？

它通过你已在使用的打包工具的插件作用于生产构建，而且默认每次构建都生成不同的输出，所以针对某次构建的模式编写的工具，到下一次构建就会失效。构建时间和输出大小，与其他混淆器的并排实测，见[对比页面](https://www.afterpack.dev/docs/comparison)。

### 混淆能隐藏 API 密钥吗？

不能。运行中的代码用到的任何东西，都能被在自己掌控的浏览器里运行它的人观察到，所以请把 API 密钥和其他秘密留在服务器上。不过编码确实能让密钥躲过 `grep` 和自动化的密钥扫描器，为你轮换一个意外发出去的密钥争取时间（[最佳实践](https://www.afterpack.dev/docs/best-practices#if-you-shipped-a-secret-by-accident)）。

---

发现了 bug，或者想要一个我们还没支持的打包工具？在 [GitHub](https://github.com/afterpack-dev/afterpack/issues) 上提一个 issue，附上你的打包工具和它的版本；我在那里看反馈。

你发布的代码，一直都是可以被读懂的。从今天起，针对一个版本写的工具，到下一个版本就会失效。

— [Nikita](https://nikitaeverywhere.com)
