diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ac12116 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +.git +.github +node_modules +**/node_modules +data +output +scripts +docs +*.md +docker-compose.yml +Dockerfile +.dockerignore +webapp/.vscode +webapp/doc +webapp/.env* +!webapp/.env.production +web +webapp/dist +webapp/node_modules +.vscode +.idea +*.log diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60c3529..d1fa6c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,6 +20,13 @@ jobs: with: go-version: '1.25.5' + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: webapp/package-lock.json + - name: Build and Package run: | chmod +x scripts/build.sh diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index e9f4cb1..8ffa194 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -17,6 +17,19 @@ jobs: with: go-version: '1.25.5' + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: webapp/package-lock.json + + - name: Build Frontend + run: | + cd webapp + npm install + npm run build + - name: Install dependencies run: go mod download diff --git a/Dockerfile b/Dockerfile index b1641be..70f8a90 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,45 @@ -FROM golang:1.25.5-alpine AS builder +# Stage 1: Build Frontend +FROM --platform=$BUILDPLATFORM node:20-alpine AS node-builder +WORKDIR /webapp +# 复制 package.json 和 lock 文件以利用 layer 缓存 +COPY webapp/package*.json ./ +# 使用 npm ci 以获得更快且可重现的构建(如果存在 package-lock.json) +RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi +# 复制其余源码并构建 +COPY webapp/ . +RUN npm run build +# Stage 2: Build Backend +FROM --platform=$BUILDPLATFORM golang:1.25.5-alpine AS builder +# 安装 Git 以支持某些 Go 模块依赖 +RUN apk add --no-cache git WORKDIR /app +# 复制 go.mod 和 go.sum 以利用 layer 缓存 COPY go.mod go.sum ./ RUN go mod download - +# 复制源码 COPY . . -RUN CGO_ENABLED=0 go build -o BingPaper . - -FROM alpine:latest +# 从 node-builder 复制构建好的 web 目录,用于 go embed +COPY --from=node-builder /web ./web +# 编译二进制,针对目标平台 +ARG TARGETOS +ARG TARGETARCH +RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" -o BingPaper . +# Stage 3: Final Image +FROM alpine:3.21 +# 安装运行时必需的证书和时区数据 +RUN apk add --no-cache ca-certificates tzdata WORKDIR /app +# 创建必要目录 +RUN mkdir -p data static +# 从构建阶段复制二进制文件 COPY --from=builder /app/BingPaper . -RUN mkdir -p data -COPY --from=builder /app/config.example.yaml ./data/config.yaml -COPY --from=builder /app/web ./web +# 复制静态资源(如果有些资源没有被 embed) +COPY --from=builder /app/static ./static +# 复制默认配置 +COPY config.example.yaml ./data/config.yaml EXPOSE 8080 +VOLUME ["/app/data"] ENTRYPOINT ["./BingPaper"] diff --git a/scripts/build.bat b/scripts/build.bat index ec8520e..6e44d51 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -1,9 +1,22 @@ @echo off setlocal enabledelayedexpansion +:: лĿĿ¼ +cd /d %~dp0.. + set APP_NAME=BingPaper set OUTPUT_DIR=output +echo ʼǰ... +cd webapp +call npm install +call npm run build +if %errorlevel% neq 0 ( + echo ǰ˹ʧ + exit /b %errorlevel% +) +cd .. + echo ʼ %APP_NAME% ƽ̨ļ... if exist %OUTPUT_DIR% rd /s /q %OUTPUT_DIR% @@ -25,7 +38,10 @@ for %%p in (%PLATFORMS%) do ( set PACKAGE_DIR=%OUTPUT_DIR%\!OUTPUT_NAME! if not exist !PACKAGE_DIR! mkdir !PACKAGE_DIR! - env GOOS=%%a GOARCH=%%b CGO_ENABLED=0 go build -o !PACKAGE_DIR!\!BINARY_NAME! main.go + set GOOS=%%a + set GOARCH=%%b + set CGO_ENABLED=0 + go build -ldflags="-s -w" -o !PACKAGE_DIR!\!BINARY_NAME! main.go if !errorlevel! equ 0 ( echo %%a/%%b ɹ diff --git a/scripts/build.ps1 b/scripts/build.ps1 index b06c01c..aa8b2d1 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -1,6 +1,21 @@ +# лĿĿ¼ +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition +if ($ScriptDir) { Set-Location (Join-Path $ScriptDir "..") } + $AppName = "BingPaper" $OutputDir = "output" +Write-Host "ʼǰ..." +Push-Location webapp +npm install +npm run build +if ($LASTEXITCODE -ne 0) { + Write-Host "ǰ˹ʧ" -ForegroundColor Red + Pop-Location + exit $LASTEXITCODE +} +Pop-Location + Write-Host "ʼ $AppName ƽ̨ļ..." if (Test-Path $OutputDir) { @@ -38,7 +53,7 @@ foreach ($Platform in $Platforms) { $env:GOOS = $OS $env:GOARCH = $Arch $env:CGO_ENABLED = "0" - go build -o (Join-Path $PackageDir $BinaryName) main.go + go build -ldflags="-s -w" -o (Join-Path $PackageDir $BinaryName) main.go if ($LASTEXITCODE -eq 0) { Write-Host " $OS/$Arch ɹ" diff --git a/scripts/build.sh b/scripts/build.sh index 31d6168..89b8fc4 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -20,6 +20,12 @@ PLATFORMS=( # 需要包含的额外文件/目录 EXTRA_FILES=("web" "config.example.yaml" "README.md") +echo "开始构建前端..." +cd webapp +npm install +npm run build +cd .. + echo "开始构建 $APP_NAME 多平台二进制文件..." # 清理 output 目录 @@ -51,7 +57,8 @@ for PLATFORM in "${PLATFORMS[@]}"; do mkdir -p "$PACKAGE_DIR" # 现在已移除 CGO 依赖,使用 CGO_ENABLED=0 以支持轻松的跨平台编译 - GOOS=$OS GOARCH=$ARCH CGO_ENABLED=0 go build -o "${PACKAGE_DIR}/${BINARY_NAME}" main.go + # 增加 -ldflags="-s -w" 以减少二进制体积 + GOOS=$OS GOARCH=$ARCH CGO_ENABLED=0 go build -ldflags="-s -w" -o "${PACKAGE_DIR}/${BINARY_NAME}" main.go if [ $? -eq 0 ]; then echo " ${OS}/${ARCH} 编译成功" diff --git a/webapp/src/views/ApiDocs.vue b/webapp/src/views/ApiDocs.vue index cf3acb8..105142a 100644 --- a/webapp/src/views/ApiDocs.vue +++ b/webapp/src/views/ApiDocs.vue @@ -344,19 +344,19 @@
copyrightlink
- 版权详情链接(指向 Bing 搜索页面)⭐ 新增
+ 版权详情链接(指向 Bing 搜索页面)
startdate
- 发布开始日期(格式:YYYYMMDD)⭐ 新增
+ 发布开始日期(格式:YYYYMMDD)
fullstartdate
- 完整发布时间(格式:YYYYMMDDHHMM)⭐ 新增
+ 完整发布时间(格式:YYYYMMDDHHMM)
hsh
- 图片唯一哈希值 ⭐ 新增
+ 图片唯一哈希值
quiz