diff --git a/.air.toml b/.air.toml index 967176e..3fd27c5 100644 --- a/.air.toml +++ b/.air.toml @@ -8,7 +8,7 @@ tmp_dir = "bin" cmd = ":" full_bin = "go run main.go server" delay = 1000 - exclude_dir = ["assets", "tmp", "vendor", "testdata", "web", "data", "envs", "configs", "bin"] + exclude_dir = ["internal/static/dist", "assets", "tmp", "vendor", "testdata", "web", "data", "envs", "configs", "bin"] exclude_file = [] exclude_regex = ["_test.go"] exclude_unchanged = false diff --git a/.gitignore b/.gitignore index cd6ee3d..5dc0118 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,7 @@ configs/config.ini agent/config.ini agent/agent.pid agent/baihu-agent -web/dist/* -!web/dist/.gitkeep +web/dist/ # IDE @@ -38,7 +37,6 @@ node_modules/ # Embedded static files (built during CI/Docker) internal/static/dist/ -!internal/static/dist/.gitkeep # Config (sensitive) configs/config.local.json diff --git a/Makefile b/Makefile index e3ce322..6482bc0 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ VERSION=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") BUILD_TIME=$(shell date '+%Y/%m/%d %H:%M:%S') LDFLAGS=-ldflags="-s -w -X 'github.com/engigu/baihu-panel/internal/constant.Version=$(VERSION)' -X 'github.com/engigu/baihu-panel/internal/constant.BuildTime=$(BUILD_TIME)'" +TAGS_WEB=-tags web + DEV_UID ?= $(shell id -u 2>/dev/null || echo 1000) DEV_GID ?= $(shell id -g 2>/dev/null || echo 1000) export DEV_UID @@ -19,16 +21,21 @@ all: build # Build frontend build-web: cd web && npm ci && npm run build - rm -rf internal/static/dist - cp -r web/dist internal/static/dist # Build the application (requires frontend to be built first) build: @mkdir -p bin CGO_ENABLED=0 $(GOBUILD) $(LDFLAGS) -o $(BINARY) main.go -# Build all (frontend + backend) -build-all: build-web build +# Build release version (Frontend + Backend with embedded assets) +release: build-web + @mkdir -p bin + rm -rf internal/static/dist + cp -r web/dist internal/static/dist + CGO_ENABLED=0 $(GOBUILD) $(LDFLAGS) $(TAGS_WEB) -o $(BINARY) main.go + +# Alias for backward compatibility +build-all: release # Build agent for all platforms build-agent: build-agent-linux-amd64 build-agent-linux-arm64 build-agent-windows-amd64 build-agent-darwin-amd64 build-agent-darwin-arm64 @@ -67,14 +74,11 @@ clean: $(GOCLEAN) rm -rf bin/ rm -rf internal/static/dist - mkdir -p internal/static/dist - touch internal/static/dist/.gitkeep rm -rf web/dist - mkdir -p web/dist - touch web/dist/.gitkeep # Clean everything: local artifacts and Docker development environment (including volumes) clean-all: clean docker-dev-clean + rm -rf web/node_modules @echo "All local artifacts and Docker dev caches have been completely wiped." # Run the application @@ -143,8 +147,10 @@ docker-dev-clean: # Help help: @echo "Available targets:" - @echo " all - Build the application (default)" - @echo " build - Build the application" + @echo " all - Build backend only (default)" + @echo " build - Build backend binary (no UI embedded)" + @echo " release - Build full release binary (with UI embedded)" + @echo " build-web - Build frontend assets only" @echo " build-agent - Build agent packages (tar.gz) for all platforms" @echo " clean - Clean built files" @echo " clean-all - Clean local files and Docker dev environment (including volumes)" diff --git a/internal/router/router.go b/internal/router/router.go index 0c72e7a..5928469 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -64,22 +64,24 @@ func Setup(c *Controllers) *gin.Engine { root = router.Group("") } - // 静态资源服务(Vue SPA),带缓存头部 staticFS := static.GetFS() - assetsGroup := root.Group("/assets") - assetsGroup.Use(cacheControl("public, max-age=31536000, immutable")) // 带哈希的资源缓存1年 - assetsGroup.StaticFS("/", http.FS(mustSubFS(staticFS, "assets"))) + if staticFS != nil { + // 静态资源服务(Vue SPA),带缓存头部 + assetsGroup := root.Group("/assets") + assetsGroup.Use(cacheControl("public, max-age=31536000, immutable")) // 带哈希的资源缓存 + assetsGroup.StaticFS("/", http.FS(mustSubFS(staticFS, "assets"))) - // logo.svg 短缓存实现 - root.GET("/logo.svg", func(ctx *gin.Context) { - data, err := static.ReadFile("logo.svg") - if err != nil { - ctx.Status(404) - return - } - ctx.Header("Cache-Control", "public, max-age=86400") // 缓存1天 - ctx.Data(200, "image/svg+xml", data) - }) + // logo.svg 短缓存实现 + root.GET("/logo.svg", func(ctx *gin.Context) { + data, err := static.ReadFile("logo.svg") + if err != nil { + ctx.Status(404) + return + } + ctx.Header("Cache-Control", "public, max-age=86400") // 缓存1天 + ctx.Data(200, "image/svg+xml", data) + }) + } // API 路由组 api := root.Group("/api/v1") diff --git a/internal/static/embed.go b/internal/static/embed.go index fe3529a..d1e6675 100644 --- a/internal/static/embed.go +++ b/internal/static/embed.go @@ -1,28 +1,20 @@ +//go:build web + package static import ( "embed" "io/fs" - "net/http" ) //go:embed dist/* var distFS embed.FS -// GetFileSystem 返回嵌入的静态文件系统 -func GetFileSystem() http.FileSystem { - subFS, err := fs.Sub(distFS, "dist") - if err != nil { - panic(err) - } - return http.FS(subFS) -} - // GetFS 返回嵌入的 fs.FS func GetFS() fs.FS { subFS, err := fs.Sub(distFS, "dist") if err != nil { - panic(err) + return nil } return subFS } diff --git a/internal/static/no_embed.go b/internal/static/no_embed.go new file mode 100644 index 0000000..6bdda4d --- /dev/null +++ b/internal/static/no_embed.go @@ -0,0 +1,16 @@ +//go:build !web + +package static + +import ( + "io/fs" + "os" +) + +func GetFS() fs.FS { + return nil +} + +func ReadFile(name string) ([]byte, error) { + return nil, os.ErrNotExist +}