# MeshRay - 标准构建流程指南 **最后更新**: 2026-03-24 **关键认识**: 前端必须先 npm build,embed.go 会被 Vite 清空! --- ## 🎯 **核心要点** ### ⚠️ **重要认识** 1. **前端修改后** → 必须执行 `npm run build` 2. **Vite 编译时** → 会清空 `dist/` 目录 3. **embed.go 被删** → 需要重新创建 4. **最后编译后端** → `go build` **错误做法** ❌: ```bash # ❌ 一直编译后端,前端不重新构建 go build go build go build ``` **正确做法** ✅: ```bash # ✅ 先构建前端,再构建后端 npm run build # 重新创建 embed.go go build ``` --- ## 📋 **完整构建流程** ### 流程图: ```mermaid graph TD A[开始] --> B{修改了什么?} B -->|前端代码 | C[npm run build] B -->|后端代码 | G C --> D[Vite 编译 dist/] D --> E[⚠️ embed.go 被删除] E --> F[重新创建 embed.go] F --> G[go clean -cache] G --> H[go build 编译后端] H --> I[重启服务] I --> J[测试访问] J --> K{成功?} K -->|是 | L[✅ 完成] K -->|否 | M[检查日志] ``` --- ## 🔧 **详细步骤** ### Step 1: 前端构建 ⭐⭐⭐ ```bash cd web npm run build ``` **输出示例**: ``` ✓ built in 13.41s ``` **生成的文件**: ``` dist/ ├── index.html ├── assets/ │ ├── index-AIAUiq89.js │ ├── Login-Brnne-RL.js ← 登录页组件 │ ├── Dashboard-DSsX0xA1.js ← 仪表盘组件 │ └── ... (共 44 个文件) ``` **注意**: - ⚠️ Vite 会清空整个 `dist/` 目录 - ⚠️ `embed.go` 会被删除 - ✅ 每次都会生成新的 hash 文件名 --- ### Step 2: 重新创建 embed.go ⭐⭐⭐ **方法 A: PowerShell 单行命令**(推荐) ```powershell @" package dist import "embed" //go:embed * var WebAssets embed.FS "@ | Out-File -FilePath "web\dist\embed.go" -Encoding utf8 -NoNewline ``` --- **方法 B: 使用 cat 命令**(Linux/Mac) ```bash cat > web/dist/embed.go << 'EOF' package dist import "embed" //go:embed * var WebAssets embed.FS EOF ``` --- **方法 C: 手动创建文件** 文件路径:`web/dist/embed.go` 内容: ```go package dist import "embed" //go:embed * var WebAssets embed.FS ``` **验证**: ```bash Test-Path "web\dist\embed.go" # 返回:True ✅ ``` --- ### Step 3: 清理 Go 缓存 ```bash go clean -cache ``` **作用**: - 清理编译器构建缓存 - 确保重新编译所有包 - 避免奇怪的编译错误 --- ### Step 4: 编译后端 ⭐⭐⭐ ```bash go build -o meshray.exe -ldflags "-s -w -H=windowsgui" ./cmd/meshray ``` **参数说明**: - `-o meshray.exe`: 输出文件名 - `-s -w`: 去除符号表和调试信息(减小体积) - `-H=windowsgui`: Windows GUI 模式(无控制台窗口) **编译时间**: 约 5-10 秒 --- ### Step 5: 重启服务 ```bash # 停止旧服务 Get-Process -Name "meshray*" -ErrorAction SilentlyContinue | Stop-Process -Force # 启动新服务 .\meshray.exe ``` **验证启动**: ```bash Get-Content "logs\meshray.log" -Tail 3 ``` **期望输出**: ```json {"message": "Starting MeshRay", "address": ":9531"} ``` --- ### Step 6: 测试访问 ```bash curl.exe http://localhost:9531/ ``` **期望返回**: ```html MeshRay - 简单、高效异地组网 ``` --- ## 🛠️ **一键构建脚本** 创建文件:`build.ps1` ```powershell #!/usr/bin/env pwsh # MeshRay 标准构建脚本 Write-Host "🔨 开始构建 MeshRay..." -ForegroundColor Cyan # 1. 前端构建 Write-Host "`n📦 步骤 1: 构建前端..." -ForegroundColor Yellow Set-Location web npm run build if ($LASTEXITCODE -ne 0) { Write-Host "❌ 前端构建失败!" -ForegroundColor Red exit 1 } Set-Location .. # 2. 重新创建 embed.go Write-Host "`n📝 步骤 2: 创建 embed.go..." -ForegroundColor Yellow @" package dist import "embed" //go:embed * var WebAssets embed.FS "@ | Out-File -FilePath "web\dist\embed.go" -Encoding utf8 -NoNewline if (-not (Test-Path "web\dist\embed.go")) { Write-Host "❌ embed.go 创建失败!" -ForegroundColor Red exit 1 } # 3. 清理 Go 缓存 Write-Host "`n🧹 步骤 3: 清理 Go 缓存..." -ForegroundColor Yellow go clean -cache # 4. 编译后端 Write-Host "`n🔨 步骤 4: 编译后端..." -ForegroundColor Yellow go build -o meshray.exe -ldflags "-s -w -H=windowsgui" ./cmd/meshray if ($LASTEXITCODE -ne 0) { Write-Host "❌ 后端编译失败!" -ForegroundColor Red exit 1 } # 5. 重启服务 Write-Host "`n🔄 步骤 5: 重启服务..." -ForegroundColor Yellow Get-Process -Name "meshray*" -ErrorAction SilentlyContinue | Stop-Process -Force Start-Sleep -Seconds 2 Start-Process ".\meshray.exe" # 6. 等待启动 Start-Sleep -Seconds 3 # 7. 测试访问 Write-Host "`n🧪 步骤 6: 测试访问..." -ForegroundColor Yellow $response = curl.exe http://localhost:9531/ -s if ($response -match "DOCTYPE") { Write-Host "`n✅ 构建成功!前端页面可访问" -ForegroundColor Green } else { Write-Host "`n❌ 测试失败!请检查日志" -ForegroundColor Red Get-Content "logs\meshray.log" -Tail 10 exit 1 } Write-Host "`n✨ 完成!" -ForegroundColor Green Write-Host "📱 访问地址:http://localhost:9531" -ForegroundColor Cyan ``` **使用方法**: ```bash .\build.ps1 ``` --- ## 📊 **常见场景处理** ### 场景 1: 只修改了前端 ```bash cd web npm run build # 重新创建 embed.go @" package dist import "embed" //go:embed * var WebAssets embed.FS "@ | Out-File -FilePath "dist\embed.go" -Encoding utf8 -NoNewline cd .. go build # 重启服务 ``` --- ### 场景 2: 只修改了后端 ```bash go clean -cache go build # 重启服务 ``` --- ### 场景 3: 前后端都修改了 ```bash # 完整流程 cd web; npm run build; cd .. # 重新创建 embed.go go clean -cache go build # 重启服务 ``` --- ### 场景 4: 快速迭代开发 **开发模式**(不嵌入静态资源): ```bash # 终端 1: 前端开发服务器 cd web npm run dev # 终端 2: 后端开发(监听变化) air # 或使用其他热重载工具 ``` **生产构建**: ```bash # 使用完整构建流程 .\build.ps1 ``` --- ## ⚠️ **常见错误与解决** ### 错误 1: embed.go 丢失 **症状**: ``` no required module provides package git.zkcoi.com/zkcoi/meshray/web/dist ``` **原因**: Vite 清空了 dist/ 目录 **解决**: ```bash # 重新创建 embed.go @" package dist import "embed" //go:embed * var WebAssets embed.FS "@ | Out-File -FilePath "web\dist\embed.go" -Encoding utf8 -NoNewline ``` --- ### 错误 2: 前端修改不生效 **症状**: 页面还是旧的 **原因**: 没有重新编译前端 **解决**: ```bash cd web npm run build # 然后重新创建 embed.go 并编译后端 ``` --- ### 错误 3: MIME 类型错误 **症状**: ``` Expected JavaScript but got text/html ``` **原因**: 路由顺序错误或浏览器缓存 **解决**: 1. 确认 `server.go` 中 StaticFS 在 NoRoute 之前 2. 清除浏览器缓存(Ctrl+Shift+R) 3. Network 标签勾选 Disable cache --- ### 错误 4: 编译产物 hash 变化 **症状**: - 这次是 `Login-ABC123.js` - 下次是 `Login-XYZ789.js` **原因**: Vite 的内容哈希策略 **解决**: 正常现象,无需处理。每次 build 都会生成新 hash --- ## 📋 **检查清单** 构建前检查: - [ ] ✅ 前端代码已保存 - [ ] ✅ 后端代码已保存 - [ ] ✅ Git 状态干净(可选) 构建中检查: - [ ] ✅ `npm run build` 成功 - [ ] ✅ embed.go 已重新创建 - [ ] ✅ `go build` 无错误 构建后检查: - [ ] ✅ 服务正常启动 - [ ] ✅ curl 测试返回 HTML - [ ] ✅ 浏览器访问正常 - [ ] ✅ Console 无错误 --- ## 💡 **最佳实践** ### 1. 开发习惯 **每次修改前端后**: ```bash npm run build # 立即测试,不要等 ``` **每次修改后端后**: ```bash go build # 重启服务测试 ``` --- ### 2. 版本控制 **.gitignore 配置**: ```gitignore # 构建产物 web/dist/* !web/dist/.gitkeep *.exe *.log # 但保留 embed.go 模板 !web/dist/embed.go.template ``` **建议**: 创建 `embed.go.template` 作为模板 --- ### 3. 自动化 **VS Code Tasks**: `.vscode/tasks.json`: ```json { "version": "2.0.0", "tasks": [ { "label": "Build Frontend", "type": "shell", "command": "npm run build", "options": { "cwd": "${workspaceFolder}/web" } }, { "label": "Build Backend", "type": "shell", "command": "go build -o meshray.exe -ldflags \"-s -w -H=windowsgui\" ./cmd/meshray", "group": "build" } ] } ``` --- ### 4. CI/CD 集成 **GitHub Actions 示例**: ```yaml name: Build on: [push, pull_request] jobs: build: runs-on: windows-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Setup Go uses: actions/setup-go@v4 with: go-version: '1.21' - name: Build Frontend run: npm run build working-directory: ./web - name: Create embed.go shell: pwsh run: | @" package dist import "embed" //go:embed * var WebAssets embed.FS "@ | Out-File -FilePath "web\dist\embed.go" -Encoding utf8 -NoNewline - name: Build Backend run: go build -o meshray.exe -ldflags "-s -w -H=windowsgui" ./cmd/meshray - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: meshray path: meshray.exe ``` --- ## 🎯 **总结** ### 核心口诀: > **前端改,npm build** > **Vite 清,embed 没** > **重新建,莫要忘** > **后端编,服务启** --- ### 关键记忆点: 1. ⭐ **前端修改必 npm build** 2. ⭐ **Vite 会清空 dist/** 3. ⭐ **embed.go 需要重建** 4. ⭐ **最后才能 go build** --- ### 一句话总结: **修改前端 → npm run build → 重建 embed.go → go build → 重启服务** --- **状态**: ✅ **正确的构建流程已明确** **下次记住**: 前端修改后先 npm build,别忘了重建 embed.go! *MeshRay - 流程规范,事半功倍!* ✨🔧