以本人项目举例:
智飞部桌面应用打包流程详解
智飞部桌面应用的打包流程设计旨在实现"一份代码,多环境分发"的目标,通过自动化的构建脚本将 Python 后端、Node.js 本地服务以及 Vue.js 前端资源整合为单个可执行文件。以下是基于项目架构的完整打包流程介绍。
环境准备与依赖安装
在执行打包操作前,需确保开发环境已具备基础的运行依赖。首先,在 Python 环境中安装核心库,包括用于构建桌面窗口的 `pywebview`、处理系统互斥量的 `pywin32` 以及图像处理库 `Pillow`。其次,进入 `node_server` 目录,执行 `npm install` 以安装 Node.js 端所需的 Express 服务及更新模块依赖。这一步确保了本地服务能够正常启动并处理前端的代理请求。
配置文件定制
项目采用 JSON 配置文件驱动应用行为,这是打包流程中实现多版本、多客户定制化的核心环节。开发者需根据目标环境(如测试环境、生产环境或特定客户定制版)准备相应的配置文件(如 `config.test.json`)。在配置文件中,需明确定义应用的基础信息(名称、版本号)、UI 表现(主题色、图标路径)、服务器地址(本地端口、远程更新地址、API 代理目标)以及窗口属性(宽高、调试模式)。通过修改这些字段,可以在不改动代码逻辑的情况下,生成不同品牌或连接不同后端服务的独立应用版本。
执行自动化打包
项目推荐使用根目录下的 `build.py` 脚本进行自动化打包,该脚本封装了 PyInstaller 的复杂参数。
-
**默认打包**:直接运行 `python build.py`,脚本将读取默认配置进行构建。
-
**指定配置打包**:运行 `python build.py config.test.json` 或简写为 `python build.py test`,脚本会自动识别并加载对应的 JSON 配置文件。
脚本执行时,会自动调用 PyInstaller,通过 `--onefile` 参数将所有资源(包括 Node.js 运行时、`node_modules`、前端 `html` 目录、Python 模块及图标资源)打包进单个 exe 文件中。同时,脚本会处理 `--hidden-import` 参数,确保 `modules` 目录下的各个功能模块(如配置加载、单实例锁、窗口管理等)被正确包含。
产物输出与验证
打包完成后,生成的可执行文件将输出至 `dist/` 目录,命名格式通常为"应用名称_版本号.exe"(例如 `智飞部_v1.0.0.exe`)。由于采用了单文件打包模式,该 exe 文件体积通常在 80-120 MB 之间(包含完整的 Node.js 环境)。开发者可直接运行该文件进行验证:应用启动时会初始化单实例互斥锁,自动拉起内置的 Node.js 本地服务,加载前端页面,并根据配置检查远端更新。
远端更新资源准备
为了实现客户端的"热更新"功能,打包流程的最后一步涉及远端资源的部署。开发者需将前端构建产物(`html` 目录下的 `index.html`、`assets`、`version.json` 等)打包为 `dist.zip` 文件,并上传至配置文件 `server.remote_base_url` 指定的远程服务器根目录。当客户端启动时,Node.js 服务会自动对比本地与远端的 `version.json`,若有新版本则自动下载并解压该 ZIP 包,从而实现无需重新安装 exe 即可更新前端业务逻辑的能力。
# 智飞部桌面应用
## 项目简介
基于 Python + Node.js + Vue.js 的桌面应用程序,使用 pywebview 提供原生桌面体验。
### 核心特性
- 🚀 **单文件打包**:PyInstaller 打包为单个 exe,分发方便
- 🔄 **自动热更新**:启动时自动检测远端 `dist.zip`,解压即用,无需重装
- 🎨 **可配置化**:一份代码 + JSON 配置文件 = 多版本/多客户/多环境
- 🔒 **单实例运行**:互斥量 + 端口锁定,防重复启动
- 🧱 **模块化架构**:Python 端按功能拆分为 `modules/`,Node 端拆分为 `lib/`
## 技术栈
| 层 | 技术 |
|---|---|
| 前端 | Vue.js + Vite |
| 本地服务 | Node.js + Express(API 代理 + 静态托管) |
| 桌面框架 | Python + pywebview(Edge WebView2) |
| 打包 | PyInstaller --onefile |
## 快速开始
### 环境准备
```bash
# Python 依赖
pip install pywebview pywin32 Pillow
# Node.js 依赖(进入 node_server 目录执行)
cd node_server
npm install
```
### 开发运行
```bash
python main.py
```
> Node.js 服务器由 Python 自动启动,无需手动操作。
### 打包 exe
#### 方式一:自动化脚本(推荐)
```bash
# 默认配置
python build.py
# 指定配置
python build.py config.test.json
# 简写(自动补全 config.xxx.json)
python build.py test
```
输出在 `dist/智飞部_v1.0.0.exe`。
#### 方式二:PyInstaller 命令行
```bash
pyinstaller --name 智飞部 --windowed --onefile ^
--icon app_icon.ico ^
--add-data "config.default.json;." ^
--add-data "node_server;node_server" ^
--add-data "html;html" ^
--add-data "modules;modules" ^
--add-data "logo.png;." ^
--hidden-import webview ^
--hidden-import modules ^
--hidden-import modules.config ^
--hidden-import modules.singleton ^
--hidden-import modules.resources ^
--hidden-import modules.server ^
--hidden-import modules.splash ^
--hidden-import modules.window ^
--hidden-import modules.app ^
main.py
```
---
## 项目结构
```
web-test/
├── main.py # 入口(编排脚本,~107 行)
├── build.py # 自动化打包脚本
├── generate_config.py # 交互式生成配置文件
│
├── modules/ # Python 功能模块
│ ├── config.py # 配置加载 & 默认值
│ ├── singleton.py # 单实例互斥锁
│ ├── resources.py # 资源路径 & 用户数据目录
│ ├── server.py # Node.js 进程管理 & 更新监控
│ ├── splash.py # 启动界面(Tkinter)
│ ├── window.py # 桌面窗口(pywebview)
│ └── app.py # 应用生命周期(重启 / 启动流程)
│
├── node_server/ # Node.js 本地服务器
│ ├── server.js # Express 主入口
│ ├── lib/
│ │ ├── download.js # 下载 & ZIP 解压工具
│ │ └── updater.js # 版本检查 & 热更新逻辑
│ ├── node.exe # Node.js 运行时
│ ├── node_modules/ # npm 依赖
│ ├── package.json
│ └── package-lock.json
│
├── html/ # 前端构建产物
│ ├── index.html
│ ├── assets/
│ └── version.json
│
├── config.default.json # 默认配置
├── config.test.json # 测试环境配置
├── logo.png # 启动 Logo
├── app_icon.ico # 应用图标
│
└── dist/ # 打包输出
└── 智飞部_v1.0.0.exe
```
---
## 配置系统
一份 JSON 文件驱动整个应用,支持多版本、多环境、多客户。
```json
{
"app": {
"name": "智飞部",
"title": "智能业务管理平台",
"window_title": "智飞部",
"version": "1.0.0"
},
"ui": {
"logo": "logo.png",
"icon": "app_icon.ico",
"theme_color": "#1890ff",
"background_color": "#f0f2f5"
},
"server": {
"port": 8080,
"host": "127.0.0.1",
"remote_base_url": "https://app.sys.zhifeibu.com",
"api_target": "https://app.sys.zhifeibu.com",
"api_prefix": "/adminapi/"
},
"update": {
"zip_filename": "dist.zip"
},
"window": {
"width": 1360,
"height": 800,
"min_width": 800,
"min_height": 600,
"debug": false
}
}
```
### 配置项说明
| 字段 | 说明 |
|---|---|
| `app.name` | 应用名称(影响用户数据目录路径) |
| `app.version` | 版本号(用于更新比较) |
| `ui.theme_color` | 启动界面主题色 |
| `server.port` | 本地服务端口 |
| `server.remote_base_url` | 远端服务器根地址(版本检查 & 更新下载) |
| `server.api_target` | API 代理目标地址 |
| `update.zip_filename` | 远端 ZIP 包文件名(默认 `dist.zip`) |
| `window.debug` | 是否开启 webview 调试工具 |
### 典型使用场景
| 场景 | 操作 |
|---|---|
| 开发环境 | `python main.py --config config.dev.json` |
| 测试环境 | `python build.py config.test.json` |
| 生产环境 | `python build.py config.prod.json` |
| 客户定制 | 修改 `app.name` + `ui.theme_color` + `server.*` 后打包 |
| 白标产品 | 替换 `logo.png` + `app_icon.ico`,调整配置即可 |
---
## 命令行参数
```bash
# 重置用户数据(清除缓存和已更新的资源)
智飞部.exe --reset
# 指定配置文件
智飞部.exe --config config.test.json
智飞部.exe -c config.test.json
```
---
## 自动更新机制
应用启动时 Node.js 服务器自动执行更新检查:
1. 读取本地 `html/version.json` 获取当前版本
2. 请求远端 `${remote_base_url}/version.json` 获取服务器版本
3. 版本号比较(语义化版本),有新版则继续
4. 下载 `dist.zip` 到临时目录
5. 清理旧 `html/` 目录,解压 `dist.zip` 覆盖
6. 前端页面自动刷新,应用新版本
> `dist.zip` 包含完整前端资源(`index.html`、`assets/`、`favicon.ico`、`version.json` 等),新增文件无需修改代码。
---
## 常见问题
### Q: 打包后 exe 文件很大?
A: 正常。因为包含了完整的 Node.js 运行时和 node_modules。`--onefile` 模式下约 80-120 MB。
### Q: 如何修改远端服务器地址?
A: 修改配置文件中 `server.remote_base_url` 和 `server.api_target`,重新打包即可。
### Q: 如何清除缓存?
A: 运行 `智飞部.exe --reset`,或手动删除 `%LOCALAPPDATA%\智飞部\html` 目录。
### Q: 能同时运行多个实例吗?
A: 不能,有单实例保护。如需多版本并行,使用不同端口配置分别打包。
### Q: 新增了 Python 模块怎么打包?
A: 在 `build.py` 的 `--hidden-import` 列表中添加新模块名,在 `main.spec` 的 `hiddenimports` 列表中同步添加。
---
## 许可证
本项目仅供学习和内部使用。