# 填色模板代码混淆方案

## 概述

对 `templates/coloring` 构建产出的 `index.html` 进行 JavaScript 代码混淆，防止竞争对手通过阅读源码窃取 WebGL 填色技术方案。

## 混淆策略

### 整体思路

构建产物中 **92% 是 base64 编码的图片/音频数据**（约 970KB），**仅 8% 是实际代码逻辑**（约 85KB）。混淆方案采用"载荷替换法"：先把 base64 数据临时替换为短占位符 → 混淆纯代码 → 还原 base64 数据。这样既能保护核心逻辑，又不会触碰或破坏二进制资源数据。

### 三层保护

| 层级 | 措施 | 工具 | 体积影响 |
|------|------|------|----------|
| 1 | 移除 console / debugger 语句 | esbuild `drop` | -0 KB |
| 2 | 禁用 sourcemap | esbuild `sourcemap: false` | -0 KB |
| 3 | JS 代码混淆 | javascript-obfuscator | +~85 KB (8%) |

### 混淆配置详解

```js
{
  compact: true,                    // 压缩输出
  controlFlowFlattening: false,     // ❌ 关闭：会严重影响 WebGL 帧率
  deadCodeInjection: false,         // ❌ 关闭：会增加 30%+ 体积
  debugProtection: false,           // ❌ 关闭：用 setInterval 浪费 CPU
  disableConsoleOutput: true,       // 双重保险移除 console
  identifierNamesGenerator: "hexadecimal", // 变量名 → _0x 十六进制
  selfDefending: false,             // ⚠️ 关闭：在大型 JS 上会产生语法错误
  simplify: true,                   // 简化表达式
  stringArray: false,               // ⚠️ 关闭：保护 base64 载荷占位符
  transformObjectKeys: false,       // ❌ 关闭：会破坏 DOM/WebGL API
  renameGlobals: false,             // ❌ 关闭：会破坏 window/document 等
}
```

### 关键决策说明

- **`controlFlowFlattening: false`** — 控制流平坦化会在运行时引入大量分支跳转，WebGL 渲染需要 60fps，任何额外开销都会导致掉帧
- **`deadCodeInjection: false`** — 注入死代码会使文件增大 30-40%，广告平台对素材体积有严格要求
- **`stringArray: false`** — 将字符串移到数组会破坏我们用于保护 base64 载荷的占位符标记。关闭后字符串字面量仍会通过其他方式混淆（如十六进制转义）
- **`selfDefending: false`** — 该选项会将整体代码包裹在 IIFE 中并通过 `.toString().search()` 校验。实测在 ~1MB 的大型单文件 JS 上会产生语法错误（生成的字符串字面量中出现未转义换行），因此关闭。关闭后 beautifier 仍可格式化代码，但十六进制变量名和括号表示法已大幅提高阅读难度

## 文件变更

### 修改的文件

**`vite.config.js`** — 新增依赖和构建后处理逻辑：

```
require("javascript-obfuscator")    // 新增依赖
obfuscateJsInHtml()                  // 新增函数：base64 保护 + JS 混淆
patchSingleFileHtml()                // 修改：调用混淆流程
esbuild.drop / build.sourcemap       // 新增配置
```

**`package.json`** — 新增 devDependency：
```json
"javascript-obfuscator": "^4.1.0"
```

### 未修改的文件

- 所有 `src/` 源码保持原样，本地开发调试不受影响
- 混淆仅在 `vite build` 生产构建时生效

## 构建命令

```bash
# 单个平台
npm run build:google     # Google Ads
npm run build:applovin   # AppLovin
npm run build:unity      # Unity Ads
npm run build:playturbo  # PlayTurbo
npm run build:mintegral  # Mintegral

# 全部平台
npm run build:all
```

## 验证方法

### 构建后自动检查

构建日志会输出找到的 base64 载荷数量：
```
[obfuscate] Found 12 base64 payloads, total 966,468 bytes
```
如果载荷数量不对，说明 base64 识别规则需要更新。

### 手动检查项

```bash
# 1. console 语句已移除
grep -c "console\." dist/google/index.html
# 期望输出: 0

# 2. base64 占位符已全部还原
grep -c "__B64_" dist/google/index.html
# 期望输出: 0

# 3. base64 图片数据完整
python3 -c "
import re
with open('dist/google/index.html') as f:
    html = f.read()
b64s = re.findall(r'data:image/[^;]*?;base64,([A-Za-z0-9+/=]+)', html)
print(f'图片资源: {len(b64s)} 个')
"

# 4. 变量名已混淆（十六进制风格）
grep -o '_0x[0-9a-f]\{4,6\}' dist/google/index.html | head -5
# 应该看到类似 _0x2fb6a9 的变量名

# 5. 属性访问已转为括号表示法
grep -o "\\['[a-zA-Z]*'\\]" dist/google/index.html | head -5
# 应该看到类似 ['defineProperty'] 的属性访问
```

### 功能验证

1. 用浏览器打开构建产物 `dist/google/index.html`
2. 确认填色游戏正常加载
3. 点击颜色按钮 — 切换正常
4. 点击填色区块 — 填色动画正常
5. 完成所有区块 — CTA 按钮出现
6. 打开 DevTools Performance 面板 — 确认帧率稳定 60fps
7. 尝试用 beautifier 格式化代码 — 应该失败或输出乱码

## 体积对比

| 指标 | 混淆前 | 混淆后 | 变化 |
|------|--------|--------|------|
| 未压缩 | ~1,058 KB | ~1,147 KB | +8% |
| Gzip | ~672 KB | ~672 KB | ±0% |

Gzip 体积几乎不变，因为混淆引入的重复模式（如 `_0x` 前缀、`['property']` 访问）压缩率高。

## 注意事项

1. **本地开发 (`npm run dev:template`) 不受影响** — 混淆仅在 `vite build` 时触发
2. **base64 载荷识别依赖固定正则** — 如果未来资源格式变化（如改用 WebP 或 AVIF），需要更新 `vite.config.js` 中的 `b64Pattern`
3. **`javascript-obfuscator` 版本锁定在 4.x** — 大版本升级可能改变配置项或行为，升级前需验证
4. **`selfDefending` 可能与极少数广告平台的脚本注入冲突** — 如遇到平台审核失败，可尝试临时关闭此选项排查
