---
title: 开发指南
description: 从源代码构建、测试和贡献 DropOut
---

# 开发指南

本指南将帮助你设置开发环境、从源代码构建 DropOut，以及为项目做出贡献。

## 前置要求

### 必需软件

1. **Rust** (最新稳定版)

   ```bash
   # 通过 rustup 安装
   curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
   ```

2. **Node.js** (v22+) 和 **pnpm** (v9+)

   ```bash
   # 从 https://nodejs.org/ 安装 Node.js
   # 安装 pnpm
   npm install -g pnpm@9
   ```

3. **系统依赖**

   按照你的平台参考 [Tauri 前置要求](https://v2.tauri.app/start/prerequisites/)：

   **Linux (Debian/Ubuntu):**

   ```bash
   sudo apt update
   sudo apt install libwebkit2gtk-4.1-dev \
     build-essential \
     curl \
     wget \
     file \
     libssl-dev \
     libayatana-appindicator3-dev \
     librsvg2-dev
   ```

   **macOS:**

   ```bash
   xcode-select --install
   ```

   **Windows:**
   - 安装 [Microsoft Visual C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
   - 安装 [WebView2](https://developer.microsoft.com/microsoft-edge/webview2/)

## 快速开始

### 克隆仓库

```bash
git clone https://github.com/HydroRoll-Team/DropOut.git
cd DropOut
```

### 安装依赖

**前端依赖：**

```bash
cd packages/ui
pnpm install
cd ../..
```

**文档依赖：**

```bash
cd packages/docs
pnpm install
cd ../..
```

### 开发模式

以开发模式运行 DropOut，支持热重载：

```bash
cargo tauri dev
```

这将：

1. 启动前端开发服务器（Vite 在 5173 端口）
2. 编译 Rust 后端
3. 打开 Tauri 窗口
4. 为前端更改启用热重载
5. 在 Rust 文件更改时重新编译

**终端输出：**

- 来自 Vite 的前端日志
- Rust 标准输出/标准错误
- 编译状态

### 构建生产版本

构建发布二进制文件：

```bash
cargo tauri build
```

**输出位置：**

- **Linux**: `src-tauri/target/release/bundle/`
  - `.deb` 软件包
  - `.AppImage` 包
- **macOS**: `src-tauri/target/release/bundle/`
  - `.dmg` 安装器
  - `.app` 包
- **Windows**: `src-tauri/target/release/bundle/`
  - `.msi` 安装器
  - `.exe` 可执行文件

## 项目结构

```
DropOut/
├── src-tauri/              # Rust 后端
│   ├── src/
│   │   ├── main.rs         # Tauri 命令和入口点
│   │   ├── core/           # 核心模块
│   │   │   ├── auth.rs     # 身份验证
│   │   │   ├── downloader.rs # 下载管理器
│   │   │   ├── fabric.rs   # Fabric 支持
│   │   │   ├── forge.rs    # Forge 支持
│   │   │   ├── java.rs     # Java 管理
│   │   │   ├── instance.rs # 实例系统
│   │   │   └── ...
│   │   └── utils/          # 工具类
│   └── Cargo.toml
├── packages/
│   ├── ui/                 # Svelte 5 前端
│   │   ├── src/
│   │   │   ├── App.svelte
│   │   │   ├── components/
│   │   │   ├── stores/     # 状态管理
│   │   │   └── lib/
│   │   └── package.json
│   └── docs/               # 文档站点
│       ├── content/docs/
│       └── package.json
├── .github/
│   └── workflows/          # CI/CD 流水线
└── scripts/                # 构建脚本
```

## 开发工作流

### 前端开发

**启动开发服务器：**

```bash
cd packages/ui
pnpm dev
```

**类型检查：**

```bash
pnpm check
```

**代码检查：**

```bash
pnpm lint
```

**格式化代码：**

```bash
pnpm format
```

### 后端开发

**运行 Rust 测试：**

```bash
cargo test
```

**检查代码：**

```bash
cargo check
```

**格式化代码：**

```bash
cargo fmt
```

**代码检查：**

```bash
cargo clippy
```

### 文档开发

**启动文档开发服务器：**

```bash
cd packages/docs
pnpm dev
```

**构建文档：**

```bash
pnpm build
```

**类型检查：**

```bash
pnpm types:check
```

## 代码风格

### Rust

遵循标准 Rust 约定：

- 使用 `cargo fmt` 格式化
- 使用 `cargo clippy` 检查
- 编写文档注释 (`///`)
- 正确处理错误
- 对 I/O 使用 async/await

**示例：**

```rust
/// Starts the Microsoft authentication device flow
#[tauri::command]
async fn start_microsoft_login(
    window: Window,
) -> Result<DeviceCodeResponse, String> {
    emit_log!(window, "Starting Microsoft login...");

    start_device_flow()
        .await
        .map_err(|e| e.to_string())
}
```

### TypeScript/Svelte

遵循项目约定：

- 使用 Svelte 5 runes (`$state`, `$effect`)
- 优先使用 TypeScript 而非 JavaScript
- 使用 Biome 进行格式化和检查
- 遵循组件结构

**示例：**

```typescript
// stores/auth.svelte.ts
export class AuthState {
  currentAccount = $state<Account | null>(null);
  isLoginModalOpen = $state(false);

  async login(username: string) {
    const account = await invoke("offline_login", { username });
    this.currentAccount = account;
  }
}
```

## 测试

### 单元测试

**Rust：**

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_offline_uuid() {
        let uuid = generate_offline_uuid("Player");
        assert!(uuid.len() > 0);
    }
}
```

**运行：**

```bash
cargo test
```

### 集成测试

测试完整应用程序：

1. 以开发模式构建：`cargo tauri dev`
2. 手动测试功能
3. 检查控制台错误
4. 验证 UI 行为

### CI 测试

GitHub Actions 在以下平台运行测试：

- Ubuntu（最新版）
- Arch Linux（Wayland）
- Windows（最新版）
- macOS（ARM64）

查看工作流：`.github/workflows/test.yml`

## 调试

### 前端调试

1. 在 Tauri 窗口中打开开发工具：`Ctrl+Shift+I`（Windows/Linux）或 `Cmd+Option+I`（macOS）
2. 检查控制台错误
3. 使用 React DevTools 或 Svelte DevTools
4. 监控网络标签页查看 API 调用

### 后端调试

**打印调试：**

```rust
emit_log!(window, format!("Debug: {}", value));
println!("Debug: {}", value);
```

**Rust 调试器：**

```bash
# 安装 rust-lldb 或 rust-gdb
cargo install rust-gdb

# 调试
rust-gdb target/debug/dropout
```

### 日志

**前端：**

```typescript
console.log("Info message");
console.error("Error message");
```

**后端：**

```rust
emit_log!(window, "Status update");
eprintln!("Error: {}", error);
```

## 贡献

### 贡献工作流

1. **Fork** 仓库
2. **创建**功能分支：
   ```bash
   git checkout -b feature/my-feature
   ```
3. **进行**更改
4. **彻底测试**
5. **提交**时使用约定式提交：
   ```bash
   git commit -m "feat: add new feature"
   ```
6. **推送**到你的 fork：
   ```bash
   git push origin feature/my-feature
   ```
7. **创建** Pull Request

### 提交消息

遵循 [约定式提交](https://www.conventionalcommits.org/)：

**格式：**

```
<type>[scope]: <description>

[optional body]

[optional footer]
```

**类型：**

- `feat`: 新功能
- `fix`: 错误修复
- `docs`: 文档
- `style`: 格式化
- `refactor`: 代码重构
- `perf`: 性能改进
- `test`: 添加测试
- `chore`: 维护

**示例：**

```bash
feat(auth): add offline authentication support
fix(java): resolve detection on Windows
docs: update installation guide
refactor(download): simplify progress tracking
```

### Pull Request 指南

**提交前：**

- [ ] 代码遵循风格指南
- [ ] 测试在本地通过
- [ ] 必要时更新文档
- [ ] 没有提交不必要的文件
- [ ] 提交消息清晰

**PR 描述：**

- 解释做了什么以及为什么
- 链接相关 issue
- 列出破坏性更改
- 为 UI 更改添加截图

### 代码审查

维护者将审查你的 PR：

- 代码质量和风格
- 测试覆盖率
- 文档
- 性能影响
- 安全影响

对反馈保持响应并进行要求的更改。

## 常见任务

### 添加 Tauri 命令

1. **在 `main.rs` 中定义命令：**

   ```rust
   #[tauri::command]
   async fn my_command(param: String) -> Result<String, String> {
       Ok(format!("Received: {}", param))
   }
   ```

2. **在构建器中注册：**

   ```rust
   .invoke_handler(tauri::generate_handler![
       my_command,
       // ... 其他命令
   ])
   ```

3. **从前端调用：**
   ```typescript
   const result = await invoke("my_command", { param: "value" });
   ```

### 添加 UI 组件

1. **创建组件文件：**

   ```svelte
   <!-- packages/ui/src/components/MyComponent.svelte -->
   <script lang="ts">
     let count = $state(0);
   </script>

   <button onclick={() => count++}>
     Count: {count}
   </button>
   ```

2. **导入并使用：**

   ```svelte
   <script>
     import MyComponent from './components/MyComponent.svelte';
   </script>

   <MyComponent />
   ```

### 添加 Store

1. **创建 store 文件：**

   ```typescript
   // packages/ui/src/stores/mystore.svelte.ts
   export class MyState {
     value = $state(0);

     increment() {
       this.value++;
     }
   }

   export const myState = new MyState();
   ```

2. **在组件中使用：**

   ```svelte
   <script>
     import { myState } from '../stores/mystore.svelte';
   </script>

   <button onclick={() => myState.increment()}>
     {myState.value}
   </button>
   ```

## 开发问题故障排除

### 构建失败

**"cannot find -lwebkit2gtk"**

```bash
# 安装 WebKit 依赖
sudo apt install libwebkit2gtk-4.1-dev
```

**"pnpm not found"**

```bash
# 安装 pnpm
npm install -g pnpm@9
```

**"Rust version too old"**

```bash
# 更新 Rust
rustup update
```

### 运行时问题

**"Failed to load dynamic library"**

- 重新构建：`cargo clean && cargo tauri dev`
- 检查库路径
- 验证已安装依赖

**"CORS error"**

- 开发模式下正常
- Tauri 自动处理 CORS

**"Hot reload not working"**

- 检查 Vite 配置
- 重启开发服务器
- 清除浏览器缓存

## 资源

- [Tauri 文档](https://v2.tauri.app/)
- [Svelte 5 文档](https://svelte.dev/docs)
- [Rust 程序设计语言](https://doc.rust-lang.org/book/)
- [DropOut 仓库](https://github.com/HydroRoll-Team/DropOut)

## 获取帮助

- **Issues**: [GitHub Issues](https://github.com/HydroRoll-Team/DropOut/issues)
- **讨论**: [GitHub Discussions](https://github.com/HydroRoll-Team/DropOut/discussions)
- **文档**: 本站点
