feat: Add embedded backend packaging for all-in-one deployment
- Add backend/run_server.py entry point for embedded deployment - Add backend/build.py PyInstaller script for backend packaging - Modify config.py to support frozen executable paths - Extend client/config.json with backend configuration section - Add backend sidecar management in Electron main process - Add Whisper model download progress reporting - Update build-client.bat with --embedded-backend flag - Update DEPLOYMENT.md with all-in-one deployment documentation This enables packaging frontend and backend into a single executable for simplified enterprise deployment. Backward compatible with existing separate deployment mode (backend.embedded: false). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,10 +18,13 @@ set "SCRIPT_DIR=%~dp0"
|
||||
set "PROJECT_DIR=%SCRIPT_DIR%.."
|
||||
set "CLIENT_DIR=%PROJECT_DIR%\client"
|
||||
set "SIDECAR_DIR=%PROJECT_DIR%\sidecar"
|
||||
set "BACKEND_DIR=%PROJECT_DIR%\backend"
|
||||
set "BUILD_DIR=%PROJECT_DIR%\build"
|
||||
|
||||
REM 預設配置
|
||||
set "SKIP_SIDECAR=false"
|
||||
set "SKIP_BACKEND=true"
|
||||
set "EMBEDDED_BACKEND=false"
|
||||
set "CLEAN_BUILD=false"
|
||||
set "API_URL="
|
||||
|
||||
@@ -35,6 +38,8 @@ if /i "%~1"=="electron" (set "COMMAND=electron" & shift & goto :parse_args)
|
||||
if /i "%~1"=="clean" (set "COMMAND=clean" & shift & goto :parse_args)
|
||||
if /i "%~1"=="help" (set "COMMAND=help" & shift & goto :parse_args)
|
||||
if /i "%~1"=="--skip-sidecar" (set "SKIP_SIDECAR=true" & shift & goto :parse_args)
|
||||
if /i "%~1"=="--skip-backend" (set "SKIP_BACKEND=true" & shift & goto :parse_args)
|
||||
if /i "%~1"=="--embedded-backend" (set "EMBEDDED_BACKEND=true" & set "SKIP_BACKEND=false" & shift & goto :parse_args)
|
||||
if /i "%~1"=="--clean" (set "CLEAN_BUILD=true" & shift & goto :parse_args)
|
||||
if /i "%~1"=="--api-url" (set "API_URL=%~2" & shift & shift & goto :parse_args)
|
||||
echo %RED%[ERROR]%NC% 未知參數: %~1
|
||||
@@ -126,6 +131,10 @@ if exist "%SIDECAR_DIR%\dist" rmdir /s /q "%SIDECAR_DIR%\dist"
|
||||
if exist "%SIDECAR_DIR%\build" rmdir /s /q "%SIDECAR_DIR%\build"
|
||||
if exist "%SIDECAR_DIR%\venv" rmdir /s /q "%SIDECAR_DIR%\venv"
|
||||
if exist "%SIDECAR_DIR%\*.spec" del /q "%SIDECAR_DIR%\*.spec"
|
||||
if exist "%BACKEND_DIR%\dist" rmdir /s /q "%BACKEND_DIR%\dist"
|
||||
if exist "%BACKEND_DIR%\build" rmdir /s /q "%BACKEND_DIR%\build"
|
||||
if exist "%BACKEND_DIR%\venv" rmdir /s /q "%BACKEND_DIR%\venv"
|
||||
if exist "%BACKEND_DIR%\*.spec" del /q "%BACKEND_DIR%\*.spec"
|
||||
|
||||
echo %GREEN%[OK]%NC% 建置目錄已清理
|
||||
goto :eof
|
||||
@@ -194,6 +203,127 @@ if exist "dist\transcriber" (
|
||||
)
|
||||
goto :eof
|
||||
|
||||
:setup_backend_venv
|
||||
echo %BLUE%[STEP]%NC% 設置 Backend 建置環境...
|
||||
|
||||
cd /d "%BACKEND_DIR%"
|
||||
|
||||
if not exist "venv" (
|
||||
echo %BLUE%[INFO]%NC% 創建虛擬環境...
|
||||
%PYTHON_CMD% -m venv venv
|
||||
)
|
||||
|
||||
echo %BLUE%[INFO]%NC% 安裝 Backend 依賴...
|
||||
call venv\Scripts\activate.bat
|
||||
python -m pip install --upgrade pip -q
|
||||
python -m pip install -r requirements.txt -q
|
||||
|
||||
echo %BLUE%[INFO]%NC% 安裝 PyInstaller...
|
||||
python -m pip install pyinstaller -q
|
||||
|
||||
echo %GREEN%[OK]%NC% Backend 建置環境就緒
|
||||
goto :eof
|
||||
|
||||
:build_backend
|
||||
echo %BLUE%[STEP]%NC% 打包 Backend (Python → 獨立執行檔)...
|
||||
|
||||
cd /d "%BACKEND_DIR%"
|
||||
|
||||
call venv\Scripts\activate.bat
|
||||
|
||||
if not exist "dist" mkdir dist
|
||||
|
||||
echo %BLUE%[INFO]%NC% 執行 PyInstaller...
|
||||
echo %BLUE%[INFO]%NC% 這可能需要幾分鐘...
|
||||
|
||||
pyinstaller ^
|
||||
--onedir ^
|
||||
--name backend ^
|
||||
--distpath dist ^
|
||||
--workpath build ^
|
||||
--specpath . ^
|
||||
--noconfirm ^
|
||||
--clean ^
|
||||
--log-level WARN ^
|
||||
--console ^
|
||||
--hidden-import=uvicorn ^
|
||||
--hidden-import=uvicorn.logging ^
|
||||
--hidden-import=uvicorn.loops ^
|
||||
--hidden-import=uvicorn.loops.auto ^
|
||||
--hidden-import=uvicorn.protocols ^
|
||||
--hidden-import=uvicorn.protocols.http ^
|
||||
--hidden-import=uvicorn.protocols.http.auto ^
|
||||
--hidden-import=uvicorn.protocols.websockets ^
|
||||
--hidden-import=uvicorn.protocols.websockets.auto ^
|
||||
--hidden-import=uvicorn.lifespan ^
|
||||
--hidden-import=uvicorn.lifespan.on ^
|
||||
--hidden-import=uvicorn.lifespan.off ^
|
||||
--hidden-import=fastapi ^
|
||||
--hidden-import=starlette ^
|
||||
--hidden-import=pydantic ^
|
||||
--hidden-import=pydantic_core ^
|
||||
--hidden-import=mysql.connector ^
|
||||
--hidden-import=mysql.connector.pooling ^
|
||||
--hidden-import=httpx ^
|
||||
--hidden-import=httpcore ^
|
||||
--hidden-import=jose ^
|
||||
--hidden-import=jose.jwt ^
|
||||
--hidden-import=cryptography ^
|
||||
--hidden-import=openpyxl ^
|
||||
--hidden-import=multipart ^
|
||||
--hidden-import=python_multipart ^
|
||||
--hidden-import=dotenv ^
|
||||
--hidden-import=app ^
|
||||
--hidden-import=app.main ^
|
||||
--hidden-import=app.config ^
|
||||
--hidden-import=app.database ^
|
||||
--hidden-import=app.auth ^
|
||||
--hidden-import=app.routers ^
|
||||
--hidden-import=app.routers.auth ^
|
||||
--hidden-import=app.routers.meetings ^
|
||||
--hidden-import=app.routers.dify ^
|
||||
--hidden-import=app.routers.health ^
|
||||
--hidden-import=app.routers.excel ^
|
||||
--collect-data=pydantic ^
|
||||
--collect-data=uvicorn ^
|
||||
run_server.py
|
||||
|
||||
if exist "dist\backend" (
|
||||
echo %BLUE%[INFO]%NC% 複製 template 目錄...
|
||||
if exist "template" (
|
||||
xcopy /s /e /y "template\*" "dist\backend\template\" >nul 2>&1
|
||||
)
|
||||
if not exist "dist\backend\record" mkdir "dist\backend\record"
|
||||
echo %GREEN%[OK]%NC% Backend 打包完成: %BACKEND_DIR%\dist\backend
|
||||
) else (
|
||||
echo %RED%[ERROR]%NC% Backend 打包失敗
|
||||
exit /b 1
|
||||
)
|
||||
goto :eof
|
||||
|
||||
:update_config_embedded
|
||||
REM 更新 config.json 以啟用 embedded backend
|
||||
if "%EMBEDDED_BACKEND%"=="false" goto :eof
|
||||
|
||||
echo %BLUE%[STEP]%NC% 啟用內嵌後端模式...
|
||||
|
||||
set "CONFIG_FILE=%CLIENT_DIR%\config.json"
|
||||
if not exist "%CONFIG_FILE%" (
|
||||
echo %YELLOW%[WARN]%NC% 找不到 config.json,跳過內嵌模式設定
|
||||
goto :eof
|
||||
)
|
||||
|
||||
REM 使用 PowerShell 更新 backend.embedded = true
|
||||
powershell -Command "$config = Get-Content '%CONFIG_FILE%' -Raw | ConvertFrom-Json; if (-not $config.backend) { $config | Add-Member -NotePropertyName 'backend' -NotePropertyValue @{} }; $config.backend.embedded = $true; $config | ConvertTo-Json -Depth 10 | Set-Content '%CONFIG_FILE%' -Encoding UTF8"
|
||||
|
||||
if errorlevel 1 (
|
||||
echo %RED%[ERROR]%NC% 更新 config.json embedded 設定失敗
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo %GREEN%[OK]%NC% 已啟用內嵌後端模式
|
||||
goto :eof
|
||||
|
||||
:setup_client
|
||||
echo %BLUE%[STEP]%NC% 設置前端建置環境...
|
||||
|
||||
@@ -303,11 +433,19 @@ if "%CLEAN_BUILD%"=="true" call :do_clean
|
||||
REM 更新 API URL(如果有指定)
|
||||
call :update_config
|
||||
|
||||
REM 更新 embedded backend 設定(如果有指定)
|
||||
call :update_config_embedded
|
||||
|
||||
if "%SKIP_SIDECAR%"=="false" (
|
||||
call :setup_sidecar_venv
|
||||
call :build_sidecar
|
||||
)
|
||||
|
||||
if "%SKIP_BACKEND%"=="false" (
|
||||
call :setup_backend_venv
|
||||
call :build_backend
|
||||
)
|
||||
|
||||
call :setup_client
|
||||
call :build_electron
|
||||
call :finalize_build
|
||||
@@ -364,19 +502,26 @@ echo clean 清理建置目錄
|
||||
echo help 顯示此幫助訊息
|
||||
echo.
|
||||
echo 選項:
|
||||
echo --api-url URL 後端 API URL (預設: http://localhost:8000/api)
|
||||
echo --skip-sidecar 跳過 Sidecar 打包
|
||||
echo --clean 建置前先清理
|
||||
echo --api-url URL 後端 API URL (預設: http://localhost:8000/api)
|
||||
echo --skip-sidecar 跳過 Sidecar 打包
|
||||
echo --skip-backend 跳過 Backend 打包 (預設)
|
||||
echo --embedded-backend 打包內嵌後端 (全包部署模式)
|
||||
echo --clean 建置前先清理
|
||||
echo.
|
||||
echo 範例:
|
||||
echo %~nx0 build 完整建置 (使用預設 localhost)
|
||||
echo %~nx0 build --api-url "http://192.168.1.100:8000/api" 指定後端 URL
|
||||
echo %~nx0 build --api-url "https://api.company.com/api" 使用公司伺服器
|
||||
echo %~nx0 sidecar 僅打包 Sidecar
|
||||
echo %~nx0 electron --skip-sidecar 僅打包 Electron
|
||||
echo %~nx0 build 完整建置 (前端+Sidecar)
|
||||
echo %~nx0 build --embedded-backend 全包部署 (含內嵌後端)
|
||||
echo %~nx0 build --api-url "http://192.168.1.100:8000/api" 指定遠端後端
|
||||
echo %~nx0 sidecar 僅打包 Sidecar
|
||||
echo %~nx0 electron --skip-sidecar 僅打包 Electron
|
||||
echo.
|
||||
echo 部署模式:
|
||||
echo 分離部署(預設): 前端連接遠端後端,使用 --api-url 指定後端地址
|
||||
echo 全包部署: 使用 --embedded-backend 將後端打包進 exe,雙擊即可運行
|
||||
echo.
|
||||
echo 注意:
|
||||
echo - 首次打包 Sidecar 需下載 Whisper 模型,可能需要較長時間
|
||||
echo - 全包部署需要額外約 50MB 空間用於後端
|
||||
echo - 確保有足夠的磁碟空間 (建議 5GB+)
|
||||
echo.
|
||||
goto :eof
|
||||
|
||||
Reference in New Issue
Block a user