437 lines
11 KiB
Markdown
437 lines
11 KiB
Markdown
# 应用打包方案对比与实现
|
||
|
||
本文档详细说明 ElectronEgg 应用的两种打包方案:纯绿色版方案 和 双版本方案。
|
||
|
||
---
|
||
|
||
## 方案对比
|
||
|
||
| 特性 | 方案一:纯绿色版 | 方案二:双版本打包 |
|
||
|------|-----------------|-------------------|
|
||
| **打包产物** | 单个便携版 exe | 安装版 exe + 便携版 exe |
|
||
| **安装过程** | 无需安装 | 安装版需安装,便携版无需 |
|
||
| **桌面快捷方式** | 应用内自动创建 | 安装版自动创建,便携版手动或自动 |
|
||
| **开始菜单** | 无 | 安装版有 |
|
||
| **卸载程序** | 无(直接删除) | 安装版有 |
|
||
| **适用场景** | 临时使用、U盘携带 | 正式部署、企业分发 |
|
||
| **用户体验** | 灵活、轻量 | 专业、完整 |
|
||
| **打包时间** | 快 | 较慢(打包两次) |
|
||
| **分发复杂度** | 简单(单文件) | 中等(两个文件) |
|
||
|
||
---
|
||
|
||
## 方案一:纯绿色版 + 自动创建快捷方式
|
||
|
||
### 特点
|
||
- ✅ 单个 exe 文件,双击即用
|
||
- ✅ 首次启动时询问是否创建桌面快捷方式
|
||
- ✅ 无需安装,无需卸载
|
||
- ✅ 适合快速分发和临时使用
|
||
|
||
### 实现步骤
|
||
|
||
#### 1. 修改打包配置
|
||
|
||
**文件**:[cmd/builder.json](../cmd/builder.json)
|
||
|
||
```json
|
||
{
|
||
"productName": "南京灿能工具",
|
||
"appId": "com.canneng.tool",
|
||
"copyright": "© 2025 hongawen",
|
||
"directories": {
|
||
"output": "out"
|
||
},
|
||
"asar": true,
|
||
"files": [
|
||
"**/*",
|
||
"!cmd/",
|
||
"!data/",
|
||
"!electron/",
|
||
"!frontend/",
|
||
"!logs/",
|
||
"!out/",
|
||
"!go/",
|
||
"!python/"
|
||
],
|
||
"extraResources": {
|
||
"from": "build/extraResources/",
|
||
"to": "extraResources"
|
||
},
|
||
"publish": [
|
||
{
|
||
"provider": "generic",
|
||
"url": "https://your-update-server.com"
|
||
}
|
||
],
|
||
"win": {
|
||
"icon": "build/icons/icon.ico",
|
||
"artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
|
||
"target": [
|
||
{
|
||
"target": "portable"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 添加自动创建快捷方式功能
|
||
|
||
**文件**:[electron/preload/lifecycle.js](../electron/preload/lifecycle.js)
|
||
|
||
在 `windowReady()` 钩子中添加以下代码:
|
||
|
||
```javascript
|
||
const { logger } = require('ee-core/log');
|
||
const { getConfig } = require('ee-core/config');
|
||
const { getMainWindow } = require('ee-core/electron');
|
||
|
||
class Lifecycle {
|
||
|
||
async ready() {
|
||
logger.info('[lifecycle] ready');
|
||
}
|
||
|
||
async electronAppReady() {
|
||
logger.info('[lifecycle] electron-app-ready');
|
||
}
|
||
|
||
async windowReady() {
|
||
logger.info('[lifecycle] window-ready');
|
||
|
||
// 延迟加载,无白屏
|
||
const { windowsOption } = getConfig();
|
||
if (windowsOption.show == false) {
|
||
const win = getMainWindow();
|
||
win.once('ready-to-show', () => {
|
||
win.show();
|
||
win.focus();
|
||
})
|
||
}
|
||
|
||
// 绿色版自动创建桌面快捷方式
|
||
await this.createDesktopShortcut();
|
||
}
|
||
|
||
/**
|
||
* 为绿色版创建桌面快捷方式
|
||
*/
|
||
async createDesktopShortcut() {
|
||
const { app, dialog, shell } = require('electron');
|
||
const path = require('path');
|
||
const fs = require('fs');
|
||
|
||
// 判断是否为便携版(绿色版)
|
||
// 安装版通常在 C:\Program Files 或 AppData\Local\Programs
|
||
const isPortable = process.platform === 'win32' &&
|
||
!process.execPath.includes('Program Files') &&
|
||
!process.execPath.includes('AppData\\Local\\Programs');
|
||
|
||
if (!isPortable) {
|
||
logger.info('[lifecycle] 非便携版,跳过快捷方式创建');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const desktopPath = app.getPath('desktop');
|
||
const shortcutPath = path.join(desktopPath, '南京灿能工具.lnk');
|
||
|
||
// 如果快捷方式已存在,跳过
|
||
if (fs.existsSync(shortcutPath)) {
|
||
logger.info('[lifecycle] 桌面快捷方式已存在');
|
||
return;
|
||
}
|
||
|
||
// 询问用户是否创建快捷方式
|
||
const result = await dialog.showMessageBox({
|
||
type: 'question',
|
||
buttons: ['创建', '跳过'],
|
||
defaultId: 0,
|
||
title: '创建桌面快捷方式',
|
||
message: '是否在桌面创建快捷方式?',
|
||
detail: '方便您下次快速启动应用'
|
||
});
|
||
|
||
if (result.response === 0) {
|
||
// Windows 下创建快捷方式
|
||
const success = shell.writeShortcutLink(shortcutPath, {
|
||
target: process.execPath,
|
||
cwd: path.dirname(process.execPath),
|
||
description: '南京灿能C端工具',
|
||
icon: process.execPath,
|
||
iconIndex: 0
|
||
});
|
||
|
||
if (success) {
|
||
logger.info('[lifecycle] 桌面快捷方式创建成功');
|
||
await dialog.showMessageBox({
|
||
type: 'info',
|
||
title: '成功',
|
||
message: '桌面快捷方式已创建',
|
||
buttons: ['确定']
|
||
});
|
||
} else {
|
||
logger.error('[lifecycle] 桌面快捷方式创建失败');
|
||
}
|
||
} else {
|
||
logger.info('[lifecycle] 用户跳过创建快捷方式');
|
||
}
|
||
} catch (error) {
|
||
logger.error('[lifecycle] 创建快捷方式时出错:', error);
|
||
}
|
||
}
|
||
|
||
async beforeClose() {
|
||
logger.info('[lifecycle] before-close');
|
||
}
|
||
}
|
||
Lifecycle.toString = () => '[class Lifecycle]';
|
||
|
||
module.exports = {
|
||
Lifecycle
|
||
};
|
||
```
|
||
|
||
#### 3. 打包命令
|
||
|
||
```bash
|
||
npm run build # 完整构建
|
||
npm run build-w # 打包 Windows 便携版
|
||
```
|
||
|
||
#### 4. 产物说明
|
||
|
||
打包完成后,在 `out/` 目录下会生成:
|
||
```
|
||
out/
|
||
└── 南京灿能工具-win-4.0.0-x64.exe (便携版,约 150-200MB)
|
||
```
|
||
|
||
---
|
||
|
||
## 方案二:双版本打包(安装版 + 便携版)
|
||
|
||
### 特点
|
||
- ✅ 提供两种版本供用户选择
|
||
- ✅ 安装版:专业、完整的安装体验
|
||
- ✅ 便携版:灵活、轻量,无需安装
|
||
- ✅ 适合正式产品发布
|
||
|
||
### 实现步骤
|
||
|
||
#### 1. 修改打包配置
|
||
|
||
**文件**:[cmd/builder.json](../cmd/builder.json)
|
||
|
||
```json
|
||
{
|
||
"productName": "南京灿能工具",
|
||
"appId": "com.canneng.tool",
|
||
"copyright": "© 2025 hongawen",
|
||
"directories": {
|
||
"output": "out"
|
||
},
|
||
"asar": true,
|
||
"files": [
|
||
"**/*",
|
||
"!cmd/",
|
||
"!data/",
|
||
"!electron/",
|
||
"!frontend/",
|
||
"!logs/",
|
||
"!out/",
|
||
"!go/",
|
||
"!python/"
|
||
],
|
||
"extraResources": {
|
||
"from": "build/extraResources/",
|
||
"to": "extraResources"
|
||
},
|
||
"nsis": {
|
||
"oneClick": false,
|
||
"allowElevation": true,
|
||
"allowToChangeInstallationDirectory": true,
|
||
"installerIcon": "build/icons/icon.ico",
|
||
"uninstallerIcon": "build/icons/icon.ico",
|
||
"installerHeaderIcon": "build/icons/icon.ico",
|
||
"createDesktopShortcut": true,
|
||
"createStartMenuShortcut": true,
|
||
"shortcutName": "南京灿能工具",
|
||
"artifactName": "${productName}-Setup-${version}.${ext}"
|
||
},
|
||
"portable": {
|
||
"artifactName": "${productName}-Portable-${version}.${ext}"
|
||
},
|
||
"publish": [
|
||
{
|
||
"provider": "generic",
|
||
"url": "https://your-update-server.com"
|
||
}
|
||
],
|
||
"win": {
|
||
"icon": "build/icons/icon.ico",
|
||
"target": [
|
||
{
|
||
"target": "nsis",
|
||
"arch": ["x64"]
|
||
},
|
||
{
|
||
"target": "portable",
|
||
"arch": ["x64"]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 便携版快捷方式功能(可选)
|
||
|
||
如果希望便携版也能自动创建快捷方式,使用**方案一**中的 `createDesktopShortcut()` 代码。
|
||
|
||
#### 3. 打包命令
|
||
|
||
```bash
|
||
npm run build # 完整构建
|
||
npm run build-w # 打包两个版本
|
||
```
|
||
|
||
#### 4. 产物说明
|
||
|
||
打包完成后,在 `out/` 目录下会生成:
|
||
```
|
||
out/
|
||
├── 南京灿能工具-Setup-4.0.0.exe (安装版,约 150MB)
|
||
└── 南京灿能工具-Portable-4.0.0.exe (便携版,约 150-200MB)
|
||
```
|
||
|
||
#### 5. 版本差异说明
|
||
|
||
**安装版 (NSIS)**:
|
||
- 需要安装到系统(默认 C:\Program Files)
|
||
- 自动创建桌面快捷方式
|
||
- 自动创建开始菜单项
|
||
- 提供卸载程序
|
||
- 支持自动更新
|
||
- 适合企业部署、长期使用
|
||
|
||
**便携版 (Portable)**:
|
||
- 单个 exe 文件
|
||
- 双击直接运行(首次会自解压)
|
||
- 无需安装,无需卸载
|
||
- 可放在 U 盘随身携带
|
||
- 适合临时使用、测试环境
|
||
|
||
---
|
||
|
||
## 快捷方式创建原理(技术细节)
|
||
|
||
### Windows 快捷方式 (.lnk)
|
||
|
||
```javascript
|
||
shell.writeShortcutLink(shortcutPath, {
|
||
target: process.execPath, // 目标程序路径
|
||
cwd: path.dirname(process.execPath), // 工作目录
|
||
description: '应用描述', // 快捷方式描述
|
||
icon: process.execPath, // 图标路径
|
||
iconIndex: 0, // 图标索引
|
||
args: '', // 启动参数(可选)
|
||
appUserModelId: 'com.app.id' // Windows 应用 ID(可选)
|
||
})
|
||
```
|
||
|
||
### 判断是否为便携版
|
||
|
||
```javascript
|
||
const isPortable = process.platform === 'win32' &&
|
||
!process.execPath.includes('Program Files') &&
|
||
!process.execPath.includes('AppData\\Local\\Programs');
|
||
```
|
||
|
||
**原理**:
|
||
- 安装版通常安装在 `C:\Program Files\YourApp\`
|
||
- 或者 `C:\Users\用户名\AppData\Local\Programs\YourApp\`
|
||
- 便携版可以在任意位置运行
|
||
|
||
---
|
||
|
||
## 推荐配置
|
||
|
||
### 企业级应用(推荐方案二)
|
||
```
|
||
✅ 提供两个版本
|
||
✅ 主推安装版(专业形象)
|
||
✅ 提供便携版作为备选
|
||
```
|
||
|
||
### 轻量工具(推荐方案一)
|
||
```
|
||
✅ 只提供便携版
|
||
✅ 应用内自动创建快捷方式
|
||
✅ 简化分发流程
|
||
```
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 便携版首次启动为什么慢?
|
||
**A**: 便携版是自解压程序,首次运行需要解压资源到临时目录(约 3-5 秒)。后续启动会快很多。
|
||
|
||
### Q2: 便携版数据存储在哪里?
|
||
**A**:
|
||
- 用户数据:`C:\Users\用户名\AppData\Roaming\你的appId\`
|
||
- 临时文件:`C:\Users\用户名\AppData\Local\Temp\`
|
||
|
||
### Q3: 如何让便携版也支持自动更新?
|
||
**A**: 需要配置 `electron-updater`,但便携版更新体验不如安装版。建议:
|
||
- 安装版:使用自动更新
|
||
- 便携版:提示用户下载新版本
|
||
|
||
### Q4: 可以同时运行两个版本吗?
|
||
**A**: 不建议。虽然技术上可行,但会导致数据冲突(共享同一个 userData 目录)。
|
||
|
||
### Q5: 如何自定义快捷方式图标?
|
||
**A**: 在 `build/icons/` 目录放置 `.ico` 文件,并在 `builder.json` 中配置:
|
||
```json
|
||
"win": {
|
||
"icon": "build/icons/custom-icon.ico"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 测试检查清单
|
||
|
||
打包完成后,请进行以下测试:
|
||
|
||
### 安装版测试
|
||
- [ ] 安装到默认路径成功
|
||
- [ ] 安装到自定义路径成功
|
||
- [ ] 桌面快捷方式正常
|
||
- [ ] 开始菜单项正常
|
||
- [ ] 应用启动正常
|
||
- [ ] 卸载程序正常
|
||
|
||
### 便携版测试
|
||
- [ ] 双击 exe 正常启动
|
||
- [ ] 首次启动自动创建快捷方式(如已实现)
|
||
- [ ] 桌面快捷方式可用
|
||
- [ ] 应用功能正常
|
||
- [ ] 关闭后再次启动正常
|
||
- [ ] 可移动到其他目录运行
|
||
|
||
---
|
||
|
||
## 参考资源
|
||
|
||
- electron-builder 官方文档: https://www.electron.build/
|
||
- NSIS 配置: https://www.electron.build/configuration/nsis
|
||
- Portable 配置: https://www.electron.build/configuration/portable
|
||
- Electron shell API: https://www.electronjs.org/docs/latest/api/shell
|
||
|
||
---
|
||
|
||
*文档创建时间: 2025-10-14*
|
||
*作者: hongawen*
|