# 混淆一个 Remix 应用

没有 @afterpack/remix 这个包。Remix 通过 Vite 构建，因此使用 @afterpack/vite，或者对构建输出运行 CLI。

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

> **没有 Remix 专用包**
>
> AfterPack 不发布 `@afterpack/remix`。Remix v2 和 React Router v7 都通过 Vite 构建,因此 [Vite 插件](https://www.afterpack.dev/zh/docs/frameworks/vite)是自然的接入方式,而无论如何 [CLI](https://www.afterpack.dev/zh/docs/cli) 都能对输出直接生效。[框架](https://www.afterpack.dev/zh/docs/frameworks)有完整对照表。

## 安装

Remix 自己的插件运行在你的 `vite.config.ts` 里,因此把 `@afterpack/vite` 放进同一个 `plugins` 数组,排在它后面:

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

```ts
// vite.config.ts
import { defineConfig } from "vite";
import { vitePlugin as remix } from "@remix-run/dev";
import { afterpackVite } from "@afterpack/vite";

export default defineConfig({
  plugins: [remix(), afterpackVite()],
});
```

或者跳过这个包,直接对构建输出运行 [CLI](https://www.afterpack.dev/zh/docs/cli)。

## 构建

该插件运行在 `generateBundle` 上,在 Vite 写入之前混淆打包产物中的每一个 JavaScript chunk。Remix 会把客户端和服务端两条腿分别构建为独立的 Vite 构建,因此插件每条腿各运行一次,只作用于那条腿自己的打包产物。如果这两条腿一起发布,并且你希望它们由同一个种子构建出来,就固定一个 [`seed`](https://www.afterpack.dev/zh/docs/config#seed)(最简单的做法是 `seed: "git"`)。[构建与 CI](https://www.afterpack.dev/zh/docs/builds) 讲了这个取舍。

用 CLI 构建的方式是一样的:先构建,然后把 AfterPack 分别指向每一个输出目录。一次典型的 Remix Vite 构建会写出 `build/client` 和 `build/server`:

```bash
npx afterpack@latest build/client --seed=git
```

请把目录作为[路径参数](https://www.afterpack.dev/zh/docs/cli#usage)传入:不指定时,CLI 会选取 `dist/`、`build/`、`out/`、`.output/` 和 `.next/` 中最新的一个,而当客户端构建和服务端构建分开混淆时,这并不是你想要的。它接受一个要遍历的目录,或一个单独的 `.js`/`.mjs`/`.cjs` 文件。对每一个你想混淆的目录各运行一次,如果它们一起发布,两次运行使用同一个 [`--seed`](https://www.afterpack.dev/zh/docs/config#seed)。两条路径调用的是同一套共享流程,因此其余一切([预设阶梯](https://www.afterpack.dev/zh/docs/presets)、[失败即中止行为](https://www.afterpack.dev/zh/docs/diagnostics#fail-closed-no-exceptions)、[产出文件](https://www.afterpack.dev/zh/docs/cli#files))都是一致的。

## 验证

[Protection Map](https://www.afterpack.dev/zh/docs/protection-map) 默认会在 Vite 输出 source map 且构建不在 CI 中(`CI=true` 或 `CI=1`)时写出;[构建模式](https://www.afterpack.dev/zh/docs/config#build-mode)不会关闭它。除非设置了 `build.sourcemap`,否则 Vite 不会输出 source map,因此请为你想查看的这次构建开启 source map 后再构建,然后打开已被 gitignore 的 `.afterpack/protectionMap.html`。它包含你的完整源码。绝不要提交它或对外提供服务。

## 选项

每一个[配置键](https://www.afterpack.dev/zh/docs/config)在这个插件里的工作方式,与 [Vite 页面](https://www.afterpack.dev/zh/docs/frameworks/vite#options)上完全相同,包括指令捕获;每个键见[配置](https://www.afterpack.dev/zh/docs/config)。

## 指令

指令是 [Pro](https://www.afterpack.dev/zh/docs/pro) 功能。在 [Free 构建](https://www.afterpack.dev/zh/docs/directives#free-builds)中，会提高保护强度的指令会让构建停止，并报错 `DIAG_PRO_DIRECTIVE_REQUIRES_KEY`。

插件会从你的源代码中读取指令。CLI 不读取指令。参见[指令](https://www.afterpack.dev/zh/docs/directives)。

## 边界情况

- **失败即中止,没有覆盖选项。** 一条 `error`/`critical` [诊断信息](https://www.afterpack.dev/zh/docs/diagnostics)、一个空结果,或者引擎无法混淆的某个文件,都会[让构建失败](https://www.afterpack.dev/zh/docs/diagnostics#exit-codes)。
- **服务端输出也只是 JavaScript。** AfterPack 会混淆它在你指向的目录中找到的任何 `.js` 文件。

## 下一步

- [框架](https://www.afterpack.dev/zh/docs/frameworks):完整对照表。
- [Vite](https://www.afterpack.dev/zh/docs/frameworks/vite):本页推荐使用的插件。
- [CLI 参考](https://www.afterpack.dev/zh/docs/cli#flags):完整的标志列表。
- [配置](https://www.afterpack.dev/zh/docs/config):每一个选项,以及哪个入口能设置它。
- [预设](https://www.afterpack.dev/zh/docs/presets):`preset` 所对应的阶梯。
- [构建与 CI](https://www.afterpack.dev/zh/docs/builds):种子、开发环境与生产环境的区别、提升同一份字节。
- [Protection Map](https://www.afterpack.dev/zh/docs/protection-map):如何阅读这份报告。
