Go + React 单文件 Web 应用模板开发指南

本文将详细介绍如何从零构建一个 Go 后端(Gin) + 前端(Vite + React) 的单文件 Web 应用模板。最终构建产物为单一可执行文件,适用于工具型应用、私有化部署系统或需统一交付的 Web 项目。

技术栈

层级技术选型
后端语言Go 1.24+
后端框架Gin
前端框架React 19.x
前端构建Vite 7.x
前端语言TypeScript 5.x
样式方案Tailwind CSS 4.x

项目目录结构

gin-frontend-template/ ├── main.go # 程序入口:路由分流与 embed 静态资源 ├── go.mod # Go 模块定义 ├── backend/ # 后端业务代码 │ └── router.go # /api 路由注册 ├── frontend/ # 前端项目 │ ├── package.json # 前端依赖配置 │ ├── vite.config.ts # Vite 构建配置 │ ├── tsconfig.json # TypeScript 根配置 │ ├── tsconfig.app.json # TypeScript 应用配置 │ ├── tsconfig.node.json # TypeScript Node 配置 │ ├── eslint.config.js # ESLint 配置 │ ├── index.html # HTML 入口 │ ├── public/ # 静态资源目录 │ ├── src/ # 前端源码 │ │ ├── main.tsx # React 应用入口 │ │ ├── App.tsx # 主应用组件 │ │ └── index.css # 全局样式 │ └── dist/ # 构建产物(会被 embed 到可执行文件) ├── scripts/ │ ├── build.sh # Unix/Linux/macOS 构建脚本 │ └── build.ps1 # Windows 构建脚本 └── build/ # 构建输出目录 

第一步:环境准备

确保你的开发环境已安装以下工具:

  • Go 1.20 或更高版本(推荐 1.24)
  • Node.js 18 或更高版本
  • npm(随 Node.js 安装)

验证安装:

go version # 应输出 Go 1.24.xnode --version npm --version 

第二步:初始化 Go 项目

# 创建项目目录mkdir -p gin-frontend-template cd gin-frontend-template # 创建后端目录mkdir backend # 初始化 Go 模块 go mod init yourmodule # 添加 Gin 依赖 go get github.com/gin-gonic/[email protected] 

2.1 创建后端路由文件

# 创建路由文件cat> backend/router.go <<'EOF' package backend import ( "net/http" "github.com/gin-gonic/gin" ) // Register 只负责注册 API func Register(r *gin.Engine) { api := r.Group("/api") { api.GET("/ping", ping) api.POST("/echo", echo) } } func ping(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) } func echo(c *gin.Context) { var body map[string]any if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "data": body, }) } EOF

2.2 创建主入口文件

cat> main.go <<'EOF' package main import ( "embed" "io/fs" "mime" "net/http" "path" "path/filepath" "strings" "github.com/gin-gonic/gin" "yourmodule/backend" ) //go:embed all:frontend/dist var assets embed.FS func frontendHandler(dist fs.FS) gin.HandlerFunc { return func(c *gin.Context) { reqPath := c.Request.URL.Path // API 永不回退 if strings.HasPrefix(reqPath, "/api/") { c.Status(http.StatusNotFound) return } // 根路径映射 index.html if reqPath == "/" { reqPath = "/index.html" } // 规范化路径,防止 ../ filePath := strings.TrimPrefix(path.Clean(reqPath), "/") ext := filepath.Ext(filePath) data, err := fs.ReadFile(dist, filePath) if err != nil { // 仅对「页面路由(无扩展名)」回退 SPA if ext == "" { if data, err = fs.ReadFile(dist, "index.html"); err == nil { c.Data(http.StatusOK, "text/html; charset=utf-8", data) return } } c.Status(http.StatusNotFound) return } ct := mime.TypeByExtension(ext) if ct == "" { ct = "application/octet-stream" } c.Data(http.StatusOK, ct, data) } } func main() { r := gin.Default() // 注册后端 API(backend 不创建 Engine) backend.Register(r) // 前端 embed distFS, err := fs.Sub(assets, "frontend/dist") if err != nil { panic(err) } r.NoRoute(frontendHandler(distFS)) // 启动 r.Run(":8080") } EOF

核心设计要点:

  1. //go:embed all:frontend/dist - 将前端构建产物嵌入到二进制文件
  2. /api/* 路径始终由后端处理,不回退
  3. 带扩展名的静态资源必须存在,否则返回 404
  4. 无扩展名的路径视为 SPA 路由,回退到 index.html

第三步:初始化前端项目

3.1 使用 Vite 创建 React + TypeScript 项目

# 在项目根目录下创建前端项目npm create vite@latest frontend -- --template react-ts # 进入前端目录cd frontend # 安装依赖npminstall# 安装 Tailwind CSSnpminstall @tailwindcss/vite -D 

3.2 配置 Vite(vite.config.ts)

# 编辑 vite.config.ts,替换为以下内容:cat> vite.config.ts <<'EOF' import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' // https://vite.dev/config/ export default defineConfig({ plugins: [react(), tailwindcss()], server: { port: 5173, proxy: { "/api": { target: "http://localhost:8080", changeOrigin: true } } } }) EOF

配置说明:

  • 开发服务器运行在 5173 端口
  • /api 请求代理到后端 localhost:8080,避免跨域问题

3.3 创建占位文件

# 在 dist 目录创建占位文件,防止空目录导致 embed 失败touch frontend/dist/.keep 

3.4 返回项目根目录

cd../..

第四步:创建构建脚本

仅支持 unix 系统

# 创建构建脚本目录mkdir -p scripts # 创建构建脚本cat> scripts/build.sh <<'SCRIPT' #!/usr/bin/env bash set -e # script -> root SCRIPT_DIR="$(cd "$(dirname"$0")"&&pwd)" ROOT_DIR="$(cd"$SCRIPT_DIR/.."&&pwd)" BUILD_DIR="$ROOT_DIR/build" # ======================== # Resolve app name from go.mod # ======================== if [ ! -f "$ROOT_DIR/go.mod" ]; then echo "error: go.mod not found in project root" exit 1 fi MODULE_PATH="$(grep'^module '"$ROOT_DIR/go.mod"|awk'{print $2}')" APP_NAME="${MODULE_PATH##*/}" # ========================# Target platform# ========================GOOS="${GOOS:-$(go env GOOS)}"GOARCH="${GOARCH:-$(go env GOARCH)}"EXT=""if["$GOOS"="windows"];thenEXT=".exe"fiOUT_NAME="${APP_NAME}-${GOOS}-${GOARCH}${EXT}"echo"module : $MODULE_PATH"echo"app : $APP_NAME"echo"target : $GOOS / $GOARCH"echo"output : build/$OUT_NAME"mkdir -p "$BUILD_DIR"# ========================# Build frontend# ========================echo"build frontend"cd"$ROOT_DIR/frontend"npminstallnpm run build touch dist/.keep # ========================# Build backend# ========================echo"build backend"cd"$ROOT_DIR"GOOS="$GOOS"GOARCH="$GOARCH"\CGO_ENABLED=0\ go build \ -trimpath \ -ldflags="-s -w"\ -o "$BUILD_DIR/$OUT_NAME"echo"build success"echo"$BUILD_DIR/$OUT_NAME" SCRIPT # 添加执行权限chmod +x scripts/build.sh 

第五步:运行与测试

5.1 开发模式

终端 1 - 启动后端:

go run .

后端服务运行在 http://localhost:8080

终端 2 - 启动前端开发服务器:

cd frontend npm run dev 

前端开发服务器运行在 http://localhost:5173,并自动代理 /api 请求到后端。

访问 http://localhost:5173,你将看到 API 测试界面,可以测试:

  • GET /api/ping - 健康检查
  • POST /api/echo - 回声测试

5.2 生产构建

Unix/macOS/Linux:

chmod +x scripts/build.sh ./scripts/build.sh 

构建产物位于 build/ 目录,命名格式:

  • yourmodule-linux-amd64
  • yourmodule-darwin-arm64
  • yourmodule-windows-amd64.exe

5.3 交叉编译

# LinuxGOOS=linux GOARCH=amd64 scripts/build.sh # WindowsGOOS=windows GOARCH=amd64 scripts/build.sh # macOS (Intel)GOOS=darwin GOARCH=amd64 scripts/build.sh # macOS (Apple Silicon)GOOS=darwin GOARCH=arm64 scripts/build.sh 

5.4 运行生产版本

# Linux/macOS ./build/yourmodule-linux-amd64 # Windows .\build\yourmodule-windows-amd64.exe 

服务同样运行在 http://localhost:8080


请求路由策略

本项目的路由策略设计如下:

路径模式处理方式
/api/*始终由 Go 后端处理,永不回退
带扩展名(.js.css.png 等)必须存在,否则返回 404
无扩展名路径视为 SPA 路由,回退至 index.html

这种设计确保:

  1. API 请求不会被前端路由拦截
  2. 静态资源文件不存在时返回 404,而非回退到首页
  3. 前端 SPA 路由(如 /dashboard/settings)能正常工作

总结

通过本文的步骤,你已经成功构建了一个完整的 Go + React 单文件 Web 应用模板。该模板具有以下特点:

  • 单一可执行文件:生产环境只需部署一个文件
  • 高效开发模式:前端热更新 + API 代理
  • 清晰的项目结构:前后端职责分明
  • 跨平台支持:支持 Linux、macOS、Windows
  • SPA 路由支持:完美支持前端路由

你可以在此基础上继续扩展,添加数据库集成、用户认证、中间件等功能,构建完整的 Web 应用。

Read more

Vivado 使用教程

Vivado 使用教程

目录 一、创建工程 二、创建文件 三、编写代码 四、仿真验证 五、配置管脚 六、生成Bitstream文件并烧录 一、创建工程 1.左边创建(或打开)工程,右侧可以快速打开最近打开过的工程。 2.来到这一步,命名工程并设置工程的存放路径(这里以D触发器为例) 3.选择RTL点击next。会来到添加文件环节(可以在这里添加.v等文件,不过后面再添加是一样的)直接点击next。 4.选择芯片型号(根据开发板选,这里随便选的),完成后点next会弹出信息概要,finish完成。         二、创建文件 完成上述步骤会进入当前界面: 1.工程管理器add sourse添加(创建)设计文件,创建文件后选择Verilog语言并命名。 2.定义端口(可选),若在这定义后,

Flutter 三方库 discord_interactions 的鸿蒙化适配指南 - 在 OpenHarmony 打造高效的社交机器人交互底座

Flutter 三方库 discord_interactions 的鸿蒙化适配指南 - 在 OpenHarmony 打造高效的社交机器人交互底座

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 discord_interactions 的鸿蒙化适配指南 - 在 OpenHarmony 打造高效的社交机器人交互底座 在现代社交应用与办公协同工具的开发中,集成强大的机器人(Bot)交互能力是提升活跃度的关键。discord_interactions 库为 Flutter 开发者提供了一套完整的、遵循 Discord 官方协议的交互模型,涵盖了从 Slash Commands(斜杠命令)到 Webhook 签名验证的核心功能。本文将深入解析如何在 OpenHarmony(鸿蒙)环境下,结合鸿蒙的安全机制与网络特性,完美适配 discord_interactions 到你的鸿蒙应用中。 前言 随着鸿蒙系统(HarmonyOS)进入原生应用开发的新纪元,跨平台社交工具的适配需求日益增长。discord_interactions 作为一个纯

智能家居集成新范式:多协议网关融合配置技术深度解析

智能家居集成新范式:多协议网关融合配置技术深度解析 【免费下载链接】XiaomiGateway3Control Zigbee, BLE and Mesh devices from Home Assistant with Xiaomi Gateway 3 on original firmware 项目地址: https://gitcode.com/gh_mirrors/xia/XiaomiGateway3 在智能家居生态系统中,多协议设备的无缝集成已成为技术实现的关键挑战。本文聚焦于基于XiaomiGateway3组件的智能设备融合方案,为中级用户提供从设备发现到高级配置的完整技术路径。 🛠️ 环境准备与组件部署 获取核心组件文件 通过Git命令获取最新版本的网关集成组件: git clone https://gitcode.com/gh_mirrors/xia/XiaomiGateway3 将下载的xiaomi_gateway3目录完整迁移至Home Assistant的custom_components路径下。此操作确保所有依赖模块(包括core/converte

ubuntu上安装OpenClaw并接入飞书机器人

ubuntu上安装OpenClaw并接入飞书机器人

大家好,我是一根甜苦瓜。今天来分享如何在本地安装openclaw并接入飞书,实现让AI给我打工。 最近AI圈更新太快了,从github copilot到cursor 到claud code ,再到codex,然后是最近火爆了的小龙虾(OpenClaw),可谓是百花齐放,应接不暇。本人也是github copilot+codex的深度用户,确实不错,所以最近打算折腾一下小龙虾,顺带教大家如何把智谱GLM 接入OpenClaw。 1. 前言 1.1 什么是openclaw 2026 年开年,AI 圈突然冒出一匹“野生黑马”——OpenClaw。这个开源个人 AI 助手项目在 GitHub 上只用了 两周时间就狂揽 15 万 Star,速度堪比开挂。 简单说,它就像给你配了一个 24 小时不下班的数字打工人: 把它部署在自己的电脑或服务器上,它就能接入 WhatsApp、Telegram、