Initial commit
This commit is contained in:
@@ -0,0 +1,590 @@
|
||||
# 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
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<title>MeshRay - 简单、高效异地组网</title>
|
||||
<script src="/assets/index-AIAUiq89.js"></script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ **一键构建脚本**
|
||||
|
||||
创建文件:`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 - 流程规范,事半功倍!* ✨🔧
|
||||
Reference in New Issue
Block a user