# 混淆一个 SvelteKit 应用

@afterpack/sveltekit：在 vite.config.ts 中 sveltekit() 之后加一行插件。

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

SvelteKit 用 [Vite](https://www.afterpack.dev/zh/docs/frameworks/vite) 构建,而 AfterPack 是在**[打包工具](https://www.afterpack.dev/zh/docs/frameworks)**这一层做集成的,因此 `@afterpack/sveltekit` 是一个很薄的包装器:`afterpackSveltekit(options)` *就是* [`afterpackVite(options)`](https://www.afterpack.dev/zh/docs/frameworks/vite),只是为了在 Kit 项目里更容易被发现而单独命名。

## 安装

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

```ts
// vite.config.ts
import { defineConfig } from "vite";
import { sveltekit } from "@sveltejs/kit/vite";
import { afterpackSveltekit } from "@afterpack/sveltekit";

export default defineConfig({
  plugins: [sveltekit(), afterpackSveltekit()],
});
```

把它放在 `sveltekit()` **之后**。具名导出是 `afterpackSveltekit`;该包还重新导出了 `afterpackVite` 和 `AfterpackViteOptions` 类型。

## 构建

`vite build` 现在会生成混淆后的输出。`vite dev` 不受影响,因为插件只运行在构建的 `generateBundle` 上,也就是在 Vite 写入打包产物之前。

无论你的适配器生成了什么 JavaScript,都会被混淆。Kit 会为客户端和服务端各运行一次 Vite,插件会在每个打包产物生成时对其进行混淆,因此 `adapter-static` 预渲染的客户端打包产物,以及 Node 或无服务器的服务端打包产物,都会被覆盖到。使用 `adapter-static` 和 `adapter-node` 时,适配器会写入 `build/`;其他适配器会写到别处。

当客户端和服务端输出作为同一次发布一起出货,并且你希望两条腿由同一个种子构建出来时,固定一个 [`seed`](https://www.afterpack.dev/zh/docs/config#seed)。`seed: "git"` 是保证这一点最简单的方式。[构建与 CI](https://www.afterpack.dev/zh/docs/builds) 讲了什么时候值得固定种子,什么时候每次构建都用新种子反而更好。

## 验证

```ts
afterpackSveltekit({ protectionMap: { enabled: true } });
```

把合并后的 [Protection Map](https://www.afterpack.dev/zh/docs/protection-map) 写入已被 gitignore 的 `.afterpack/protectionMap.html`。source map 的副作用和处理规则与 [`@afterpack/vite`](https://www.afterpack.dev/zh/docs/frameworks/vite#verify) 相同。

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

使用 `adapter-static` 或 `adapter-node` 时，要检查一次部署，请在上传前运行 `npx afterpack@latest verify build`。adapter 会把受保护的客户端输出从 `.svelte-kit/output/client` 复制到 `build/`，[`verify`](https://www.afterpack.dev/zh/docs/cli#afterpack-verify-dir) 按该输出的保护回执检查这份副本，并点名任何被改动的文件。

## 选项

每一个[配置键](https://www.afterpack.dev/zh/docs/config)都可以作为选项对象在这里传入,并会逐字转发给 [`@afterpack/vite`](https://www.afterpack.dev/zh/docs/frameworks/vite#options)。类型别名 `AfterpackSveltekitOptions` 就是 `AfterpackViteOptions`。

```ts
afterpackSveltekit({ seed: "git", preset: "medium" });
```

## 指令

`.svelte` 文件内部的 `/* @afterpack … */` 标记不会被捕获。请把指令放在路由所导入的普通 `.ts`/`.js` 模块里。`src/lib/` 是自然的存放位置:

```ts
// src/lib/license.ts
/* @afterpack preset=hard */
export function verify(token: string) {
  // ...
}
/* @afterpack end */
```

无论如何,每一个生成的 chunk 都会被混淆;只有指令需要放在普通模块里。

## 下一步

- [框架](https://www.afterpack.dev/zh/docs/frameworks):完整对照表。
- [Vite](https://www.afterpack.dev/zh/docs/frameworks/vite):实际执行工作的插件。
- [Svelte](https://www.afterpack.dev/zh/docs/frameworks/svelte):普通的(非 Kit)Svelte 应用。
- [Protection Map](https://www.afterpack.dev/zh/docs/protection-map):如何阅读这份报告。
- [构建与 CI](https://www.afterpack.dev/zh/docs/builds):种子、开发环境与生产环境的区别、提升同一份字节。
