# 混淆一次 Rollup 构建

@afterpack/rollup 从你的源代码中读取指令，并在 Rollup 写入输出之前，在 generateBundle 中运行引擎。

Source: https://www.afterpack.dev/zh/docs/frameworks/rollup

`@afterpack/rollup` 与 [`@afterpack/vite`](https://www.afterpack.dev/zh/docs/frameworks/vite) 镜像:Rollup 正是 Vite 构建所依托的基础,因此同样的做法在这里也适用。它从你的源代码中读取指令,然后在 `generateBundle` 中运行引擎,此时完整的打包产物就在内存里,而 Rollup 还没有写入其中任何一部分。

## 安装

```bash
npm install -D @afterpack/rollup
```

```js
// rollup.config.mjs
import { afterpackRollup } from "@afterpack/rollup";

export default {
  input: "src/index.js",
  output: { dir: "dist", format: "es", sourcemap: true },
  plugins: [afterpackRollup()],
};
```

具名导出是 `afterpackRollup`。

## 构建

该插件以 `order: "post"` 运行在 `generateBundle` 中,因此它是最后一个接触打包产物的钩子。它会混淆打包产物中持有的每一个 JavaScript chunk 并交还回去,因此 Rollup 写入的是混淆后的 chunk,而绝不会写入原始内容。一次失败的混淆会让输出目录保持原样。

每个 chunk 的文件名都[跟随其混淆后的字节](https://www.afterpack.dev/zh/docs/builds#file-names-and-caching),打包产物中预压缩的 `.gz` 和 `.br` 副本也会根据混淆后的字节重新生成。

## 验证

在[生产构建](https://www.afterpack.dev/zh/docs/config#build-mode)中显式请求 [Protection Map](https://www.afterpack.dev/zh/docs/protection-map):

```js
afterpackRollup({ protectionMap: { enabled: true } });
```

它会落在已被 gitignore 的 `.afterpack/protectionMap.html` 中。开启 `output.sourcemap` 时,它会渲染出你的原始源码;如果没有,就没有可渲染的内容,报告会说明这一点。报告包含你的完整源码。绝不要提交它或对外提供服务。

*(live Protection Map demo embed — see https://www.afterpack.dev/protection-map-demo)*

## 选项

每一个[配置键](https://www.afterpack.dev/zh/docs/config)都可以作为选项对象在这里传入,例如 `afterpackRollup({ preset: "hard", complexity: 40 })`。

## 指令

插件会在压缩之前从你的源代码中读取指令,因此[指令](https://www.afterpack.dev/zh/docs/directives)能在打包过程中存活下来。

```js
/* @afterpack preset=hard */
export function signRequest(payload) {
  // ...
}
/* @afterpack end */
```

捕获会跳过 `node_modules`、虚拟模块和非 JS/TS 文件。[语法](https://www.afterpack.dev/zh/docs/directives#writing-one)在各处都是一样的。

## 边界情况

### 多个输出

一个配置了两个输出的构建会对每个输出各运行一次 `generateBundle`,每次运行只能看到自己的打包产物。无论输出写到哪个目录,都不会有任何内容被混淆两次:

```js
output: [
  { dir: "dist/esm", format: "es", entryFileNames: "lib.js" },
  { dir: "dist/cjs", format: "cjs", entryFileNames: "lib.cjs" },
],
plugins: [afterpackRollup({ seed: "git" })],
```

对一起发布的多个输出固定同一个 [`seed`](https://www.afterpack.dev/zh/docs/config#seed)。

### 库构建

AfterPack 运行在 Rollup 已经构建好的打包产物之上,因此你的使用者导入的每一个导出名称都会按原样保留;只有内部实现会被重命名和重构。

## 下一步

- [框架](https://www.afterpack.dev/zh/docs/frameworks):完整对照表。
- [Vite](https://www.afterpack.dev/zh/docs/frameworks/vite):同样的钩子,搭配 Vite 自己的配置解析。
- [构建与 CI](https://www.afterpack.dev/zh/docs/builds):种子、开发环境与生产环境的区别、提升同一份字节。
- [Protection Map](https://www.afterpack.dev/zh/docs/protection-map):如何阅读这份报告。
- [指令](https://www.afterpack.dev/zh/docs/directives):每一个标记键,以及它的作用。
- [配置](https://www.afterpack.dev/zh/docs/config):引擎的配置面。
