@flun/desktop-builder 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # 变更日志
2
+ ## [1.01] - 2026-07-03 10:38
3
+ ### 首发
4
+ - 将任意 Node.js 网站一键打包为当前桌面应用('win', 'mac', 'linux')(基于 Electron),支持高度自定义配置;
package/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ ISC 开源许可声明
2
+ 版权信息
3
+ Copyright (c) 2026, flun <open@flun.top>
4
+
5
+ 使用条款
6
+ 本软件以“原样”提供,任何人都可以自由地:
7
+
8
+ 使用:用于任何目的,包括商业用途。
9
+
10
+ 修改:根据需要改编代码。
11
+
12
+ 分发:免费或收费地分享原版或修改后的软件。
13
+
14
+ 唯一的条件是:不能从事非法及其它不正当行为,否则由您自行承担全部责任。
15
+
16
+ 免责声明
17
+ 作者对软件的质量不作任何保证。因使用本软件而产生的任何问题(如数据丢失、系统故障等),作者不承担任何责任。
package/README.md ADDED
@@ -0,0 +1,596 @@
1
+ # @flun/desktop-builder
2
+
3
+ > 将任意 Node.js 网站一键打包为当前桌面应用('win', 'mac', 'linux')(基于 Electron),支持高度自定义配置;
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@flun/desktop-builder.svg)](https://www.npmjs.com/package/@flun/desktop-builder)
6
+ [![license](https://img.shields.io/npm/l/@flun/desktop-builder.svg)](https://github.com/OpenFlun/desktop-builder/blob/main/LICENSE)
7
+ [![node](https://img.shields.io/node/v/@flun/desktop-builder.svg)](https://nodejs.org)
8
+
9
+ ---
10
+
11
+ ## 📖 简介
12
+
13
+ `@flun/desktop-builder` 是一个 **将本地 Node.js Web 应用打包成桌面安装包** 的构建工具;
14
+ 你只需提供一个配置文件,即可生成 Windows(NSIS)、macOS(DMG/ZIP)或 Linux(AppImage/Deb/RPM 等)安装程序;
15
+
16
+ **核心机制**:
17
+ - 该工具会将您的 Node.js 后端服务代码(由 `serverPath` 指定)与 Electron 前端整合,打包为一个独立的桌面应用;
18
+ - **Electron 本身内置了 Node.js 运行时**,因此打包后的应用在启动时,会使用**自带的 Node.js** 在后台自动运行您的服务脚本;
19
+ - 最终用户**无需在电脑上安装 Node.js 或任何其他运行时环境**,双击桌面图标即可直接使用;
20
+
21
+ ---
22
+
23
+ ## ✨ 特性
24
+
25
+ - 🚀 **一键打包**:基于 `electron-builder`,快速生成当前平台的安装包;
26
+ - ⚙️ **高度可配置**:通过单一 `desktopAppConfig.js` 控制窗口、图标、菜单、安装选项、签名、压缩等;
27
+ - 🖥️ **跨平台支持**:Windows、macOS、Linux(仅构建当前运行平台,但支持输出多种格式);
28
+ - 🔌 **自带 Node.js 运行时**:利用 Electron 内置的 Node.js 执行后端服务,用户无需额外安装;
29
+ - 📦 **灵活的安装选项**:NSIS 支持一键/向导模式,DMG 支持自定义背景、布局,Linux 支持多种包格式;
30
+ - 🎨 **品牌自定义**:应用图标、安装/卸载图标、DMG 卷宗图标、背景图片等;
31
+ - 🧩 **菜单自定义**:完全自定义应用菜单(语言、角色、点击回调,甚至内联函数);
32
+ - 📁 **精细排除**:可排除不需要的文件、依赖包和最终输出文件;
33
+ - 🔧 **可扩展**:允许直接添加 `electron-builder` 任意配置字段,并支持后处理钩子;
34
+
35
+ ---
36
+
37
+ ## 📦 安装
38
+
39
+ 在你的项目目录下安装为开发依赖:
40
+
41
+ ```bash
42
+ npm install -D @flun/desktop-builder
43
+ ```
44
+
45
+ 安装完成后,`postinstall` 脚本会自动将 `desktopAppConfig.js` 配置文件模板复制到你的项目根目录(如果不存在);
46
+
47
+ ---
48
+
49
+ ## 🚀 快速开始
50
+
51
+ ### 1. 配置 `desktopAppConfig.js`
52
+
53
+ 在项目根目录创建或编辑 `desktopAppConfig.js`,填写必填字段:
54
+
55
+ ```javascript
56
+ export default {
57
+ serverPath: './server.js', // Node.js 启动脚本路径
58
+ appUrl: 'http://www.abc.com:7296', // 启动后访问的地址
59
+ appName: '我的桌面应用', // 应用显示名称
60
+ };
61
+ ```
62
+
63
+ ### 2. 构建桌面应用
64
+
65
+ 1. 执行构建命令(根据当前系统生成对应安装包):
66
+
67
+ ```bash
68
+ npx desktop-builder build
69
+ ```
70
+ 2. 编程方式构建
71
+ ```js
72
+ import { build } from '@flun/desktop-builder';
73
+ await build();
74
+ ```
75
+ 首次运行会下载 Electron 运行时(约 100MB),请耐心等待;
76
+ 构建完成后,安装包将输出到 `./dist` 目录(可通过 `build.outputDir` 自定义);
77
+
78
+ ---
79
+
80
+ ## ⚙️ 完整配置项
81
+
82
+ 所有配置均在 `desktopAppConfig.js` 中定义,字段说明如下(`*` 为必填):
83
+
84
+ | 字段 | 类型 | 默认值 | 说明 |
85
+ | --------------------- | ---------- | -------- | ----------------------------------------------------------------- |
86
+ | **`serverPath`** | `string` | **必填** | Node.js 启动脚本路径(相对于项目根目录) |
87
+ | **`appUrl`** | `string` | **必填** | 应用访问地址(如 `http://localhost:7296`) |
88
+ | **`appName`** | `string` | **必填** | 应用显示名称(标题栏、快捷方式、安装程序等) |
89
+ | `enableLogging` | `boolean` | `false` | 是否启用日志文件(调试用),日志会写入桌面 `myapp_debug.log` |
90
+ | `window` | `object` | 见下方 | 主窗口外观与行为配置(部分字段会被强制覆盖,请注意说明) |
91
+ | `branding` | `object` | 见下方 | 图标品牌配置 |
92
+ | `menu` | `array` | 见示例 | 应用菜单模板(支持角色、分隔符、点击回调) |
93
+ | `build` | `object` | 见下方 | 打包输出配置(可随意添加 `electron-builder` 支持的其他字段) |
94
+ | `advanced` | `object` | 见下方 | 高级运行行为 |
95
+ | `excludeFiles` | `string[]` | `[]` | 复制到临时目录时排除的文件/目录(支持 glob) |
96
+ | `excludeDependencies` | `string[]` | `[]` | 从最终依赖列表中移除的 npm 包名(不会打包) |
97
+ | `excludeOutputs` | `string[]` | `[]` | 从最终输出目录中排除的安装包文件(如 `*.blockmap`、`latest.yml`) |
98
+
99
+ ---
100
+
101
+ ### 窗口配置 (`window`)
102
+
103
+ ```javascript
104
+ window: {
105
+ width: 1200, // 默认宽度 (px)
106
+ height: 800, // 默认高度 (px)
107
+ minWidth: 800, // 最小宽度
108
+ minHeight: 600, // 最小高度
109
+ maxWidth: undefined, // 最大宽度(不限制则留空)
110
+ maxHeight: undefined, // 最大高度(不限制则留空)
111
+ resizable: true, // 是否可调整大小
112
+ fullscreenable: true, // 是否允许全屏
113
+ alwaysOnTop: false, // 是否始终置顶
114
+ frame: true, // 是否显示窗口边框(标题栏、关闭按钮)
115
+ titleBarStyle: 'default', // 标题栏样式:'default' | 'hidden' | 'hiddenInset'(仅 macOS)
116
+ backgroundColor: '#ffffff', // 加载时的背景色
117
+ show: false, // 是否立即显示窗口(false 可等页面渲染后再显示,防白屏)
118
+ webPreferences: {
119
+ // ⚠️ 以下三项会被强制覆盖,配置无效(实际运行值以强制为准):
120
+ nodeIntegration: false, // 实际强制为 true
121
+ contextIsolation: true, // 实际强制为 false
122
+ sandbox: false, // 实际强制为 false
123
+
124
+ // ✅ 其他 webPreferences 属性均可自由配置,例如:
125
+ plugins: true,
126
+ webSecurity: true,
127
+ allowRunningInsecureContent: false,
128
+ enableWebAuthn: true,
129
+ // ... 更多 electron 支持选项
130
+ },
131
+ }
132
+ ```
133
+
134
+ > **⚠️ 重要安全与行为警告**
135
+ > 由于本工具需要从渲染进程启动和管理 Node.js 后端服务,`electron-main.js` 在创建窗口时会**强制覆盖** `webPreferences` 中的 `nodeIntegration`、`contextIsolation` 和 `sandbox` 三个属性:
136
+ > - `nodeIntegration: true` (开启,渲染进程可使用 Node.js API)
137
+ > - `contextIsolation: false`(关闭,渲染进程可直接访问 Electron 模块)
138
+ > - `sandbox: false` (关闭,以保证服务能够正常运行)
139
+ >
140
+ > **这意味着:**
141
+ > - 您在配置中设置的这三项 **不会生效**,实际运行时将以强制值为准;
142
+ > - **渲染进程拥有完整的 Node.js 能力**,因此**请确保您的应用仅加载受信任的本地内容**,不要加载任何外部网页,否则存在严重安全风险;
143
+ > - 此设计是为了保证后端服务自动启动等核心功能正常工作,**不建议用户尝试重新关闭这些选项**,否则可能导致应用无法运行;
144
+ > - 除上述三项外,其他 `webPreferences` 选项(如 `plugins`、`webSecurity`、`enableWebAuthn` 等)**均正常生效**,您可以按需配置;
145
+
146
+ ---
147
+
148
+ ### 品牌图标 (`branding`)
149
+
150
+ ```javascript
151
+ branding: {
152
+ appIcon: null, // 应用图标路径(建议 512×512 PNG),默认使用包内置图标
153
+ installerIcon: null, // Windows 安装程序图标(必须 .ico),默认使用包内置图标
154
+ uninstallerIcon: null, // Windows 卸载程序图标(必须 .ico),默认使用包内置图标
155
+ }
156
+ ```
157
+
158
+ - 路径相对于项目根目录;
159
+ - 若未提供或文件不存在,将使用 `@flun/desktop-builder` 内置的默认图标;
160
+
161
+ ---
162
+
163
+ ### 菜单配置 (`menu`)
164
+
165
+ 支持 Electron 标准菜单模板,可自由修改语言和结构;示例:
166
+
167
+ ```javascript
168
+ menu: [
169
+ {
170
+ label: '文件',
171
+ submenu: [
172
+ { role: 'close', label: '关闭' },
173
+ { type: 'separator' },
174
+ { role: 'quit', label: '退出' }
175
+ ]
176
+ },
177
+ // ... 更多菜单
178
+ ]
179
+ ```
180
+
181
+ - 支持 `role`(标准角色)、`label`、`type`、`click` 等;
182
+ - 特殊字符串 `'__TOGGLE_BROWSER__'` 会被替换为“在浏览器中打开”功能(调用系统默认浏览器打开 `appUrl`);
183
+ - `click` 也可直接写函数字符串(需可被 `eval` 执行,例如 `"() => { ... }"`);
184
+
185
+ ---
186
+
187
+ ### 打包配置 (`build`)
188
+
189
+ `build` 对象除了下面列出的常用子字段,**还支持直接写入任何 `electron-builder` 官方支持的配置项**(如 `compression`、`extraResources`、`publish` 等),它们会被合并到最终 `builder.json` 中;
190
+
191
+ ```javascript
192
+ build: {
193
+ appId: 'com.example.app', // 应用唯一标识(反向域名格式)
194
+ outputDir: './dist', // 安装包输出目录
195
+
196
+ // ----- Windows 配置 -----
197
+ win: {
198
+ target: ['nsis'], // 可指定 nsis/portable/zip 等
199
+ // 其他可选:icon, publisherName, signingHashAlgorithms 等
200
+ },
201
+ nsis: {
202
+ oneClick: false, // true=一键安装,false=向导安装
203
+ perMachine: true, // true=安装到所有用户(需管理员),false=当前用户
204
+ allowToChangeInstallationDirectory: true, // 是否允许用户更改安装目录
205
+ createDesktopShortcut: true, // 创建桌面快捷方式
206
+ createStartMenuShortcut: true, // 创建开始菜单快捷方式
207
+ shortcutName: '我的桌面应用', // 快捷方式名称(默认为 appName)
208
+ deleteAppDataOnUninstall: false, // 卸载时是否删除用户数据
209
+ },
210
+
211
+ // ----- macOS 配置(增强) -----
212
+ mac: {
213
+ target: ['dmg', 'zip'], // 同时生成 dmg 和 zip(zip 可用于自动更新)
214
+ // 可选高级字段(代码签名、entitlements 等)
215
+ // identity: 'Developer ID Application: Your Name (TEAM123)',
216
+ // hardenedRuntime: true,
217
+ // entitlements: './build/entitlements.mac.plist',
218
+ // entitlementsInherit: './build/entitlements.mac.inherit.plist',
219
+ },
220
+ dmg: {
221
+ iconSize: 128,
222
+ window: {
223
+ width: 540,
224
+ height: 380,
225
+ },
226
+ // 增强选项(可选)
227
+ // background: './build/dmg-background.png', // 背景图片
228
+ // backgroundColor: '#ffffff', // 背景色
229
+ // icon: './build/volume-icon.icns', // 卷宗图标
230
+ // title: '${productName} ${version}', // 卷宗名称
231
+ // format: 'UDZO', // 压缩格式
232
+ // contents: [ // 自定义图标布局
233
+ // { x: 130, y: 220, type: 'file' },
234
+ // { x: 410, y: 220, type: 'link', path: '/Applications' }
235
+ // ]
236
+ },
237
+
238
+ // ----- Linux 配置(增强) -----
239
+ linux: {
240
+ target: ['AppImage', 'deb'], // 可同时生成多种格式
241
+ category: 'Development', // 系统菜单分类
242
+ // 可选高级字段
243
+ // description: '完整的应用描述',
244
+ // synopsis: '简短描述',
245
+ // maintainer: '你的名字 <email@example.com>',
246
+ // vendor: '我的公司',
247
+ // executableArgs: ['--enable-features=...'],
248
+ // desktop: { // 自定义 .desktop 文件
249
+ // entry: {
250
+ // Name: '我的应用',
251
+ // Comment: '一个很棒的应用',
252
+ // Categories: 'Development;Utility;',
253
+ // Keywords: 'app;tool;',
254
+ // Terminal: false,
255
+ // Type: 'Application'
256
+ // }
257
+ // },
258
+ // syncDesktopName: true,
259
+ },
260
+ // 特定格式的额外配置(可选)
261
+ // appImage: { systemIntegration: 'doNotAsk' },
262
+ // deb: { depends: ['libgtk-3-0'] },
263
+ }
264
+ ```
265
+
266
+ > **平台说明**:构建时只生成**当前运行操作系统**对应的安装包(例如 Windows 下只生成 `.exe`);但您可以通过 `mac.target` / `linux.target` 同时生成多种格式(如 macOS 同时生成 `.dmg` 和 `.zip`);
267
+
268
+ ---
269
+
270
+ ### 高级选项 (`advanced`)
271
+
272
+ ```javascript
273
+ advanced: {
274
+ autoStartServer: true, // 应用启动时自动运行后端服务
275
+ autoKillServer: true, // 应用退出时自动关闭后端服务
276
+ }
277
+ ```
278
+
279
+ ---
280
+
281
+ ### 排除文件 (`excludeFiles`)
282
+
283
+ 在复制项目文件到临时构建目录时,排除指定的文件或目录(支持 glob 模式);
284
+ 示例:
285
+
286
+ ```javascript
287
+ excludeFiles: [
288
+ '.vscode/',
289
+ '.git/',
290
+ 'node_modules/', // ← 默认排除,以优化构建速度和安装体验
291
+ 'dist/',
292
+ '*.log',
293
+ './yarn.lock',
294
+ ]
295
+ ```
296
+
297
+ - 以 `/` 结尾表示目录及其内容;
298
+ - 以 `./` 开头表示仅匹配根目录下的文件(非递归);
299
+ - 否则匹配任意路径的该模式(`minimatch` 全局匹配);
300
+
301
+ ---
302
+
303
+ ### 排除依赖包 (`excludeDependencies`)
304
+
305
+ 从最终安装的依赖列表中移除指定的 npm 包(这些包不会被安装到应用内);
306
+ 常用于排除构建工具自身依赖(如 `@flun/desktop-builder`);
307
+
308
+ ```javascript
309
+ excludeDependencies: [
310
+ '@flun/desktop-builder',
311
+ '@flun/windows'
312
+ ]
313
+ ```
314
+
315
+ ---
316
+
317
+ ### 排除输出文件 (`excludeOutputs`)
318
+
319
+ 在将构建好的安装包从临时目录复制到最终输出目录时,排除某些文件(如 `*.blockmap`、`latest.yml`);
320
+
321
+ ```javascript
322
+ excludeOutputs: [
323
+ '*.blockmap',
324
+ 'latest.yml'
325
+ ]
326
+ ```
327
+
328
+ > 注意:此过滤**不影响** `electron-builder` 的构建过程,仅影响复制到输出目录的文件;
329
+
330
+ ---
331
+
332
+ ## 🖥️ 完整配置示例
333
+
334
+ 以下是一个包含所有常用配置的 `desktopAppConfig.js` 示例:
335
+
336
+ ```javascript
337
+ export default {
338
+ serverPath: './server.js',
339
+ appUrl: 'http://www.abc.com:7296',
340
+ appName: 'My Express App',
341
+ enableLogging: false,
342
+
343
+ window: {
344
+ width: 1280,
345
+ height: 720,
346
+ minWidth: 800,
347
+ minHeight: 600,
348
+ resizable: true,
349
+ frame: true,
350
+ show: false,
351
+ backgroundColor: '#f0f0f0',
352
+ webPreferences: {
353
+ // 以下三项强制覆盖,配置无效
354
+ nodeIntegration: false,
355
+ contextIsolation: true,
356
+ sandbox: false,
357
+ // 其他有效配置
358
+ plugins: true,
359
+ webSecurity: true,
360
+ },
361
+ },
362
+
363
+ branding: {
364
+ appIcon: './assets/icon.png',
365
+ installerIcon: './assets/setup.ico',
366
+ uninstallerIcon: './assets/uninstall.ico',
367
+ },
368
+
369
+ menu: [
370
+ {
371
+ label: '文件',
372
+ submenu: [
373
+ { role: 'close', label: '关闭' },
374
+ { type: 'separator' },
375
+ { role: 'quit', label: '退出' }
376
+ ]
377
+ },
378
+ // ... 其他菜单
379
+ ],
380
+
381
+ build: {
382
+ appId: 'com.mycompany.myapp',
383
+ outputDir: './release',
384
+
385
+ win: { target: ['nsis'] },
386
+ nsis: {
387
+ oneClick: false,
388
+ perMachine: true,
389
+ allowToChangeInstallationDirectory: true,
390
+ createDesktopShortcut: true,
391
+ createStartMenuShortcut: true,
392
+ shortcutName: '我的应用',
393
+ deleteAppDataOnUninstall: false,
394
+ },
395
+
396
+ mac: {
397
+ target: ['dmg', 'zip'],
398
+ // 如需签名,请取消注释并填写
399
+ // identity: 'Developer ID Application: My Company (TEAM123)',
400
+ // hardenedRuntime: true,
401
+ },
402
+ dmg: {
403
+ iconSize: 128,
404
+ window: { width: 540, height: 380 },
405
+ background: './build/dmg-background.png',
406
+ backgroundColor: '#ffffff',
407
+ title: '${productName} ${version}',
408
+ contents: [
409
+ { x: 130, y: 220, type: 'file' },
410
+ { x: 410, y: 220, type: 'link', path: '/Applications' }
411
+ ]
412
+ },
413
+
414
+ linux: {
415
+ target: ['AppImage', 'deb'],
416
+ category: 'Development',
417
+ description: '一个功能强大的应用',
418
+ maintainer: '我的名字 <my@email.com>',
419
+ vendor: '我的公司',
420
+ desktop: {
421
+ entry: {
422
+ Name: '我的应用',
423
+ Comment: '一个很棒的应用',
424
+ Categories: 'Development;Utility;',
425
+ Keywords: 'app;tool;',
426
+ Terminal: false,
427
+ Type: 'Application'
428
+ }
429
+ },
430
+ syncDesktopName: true,
431
+ },
432
+ // 额外 electron-builder 字段(示例)
433
+ compression: 'maximum',
434
+ extraResources: [{ from: './assets', to: './assets' }],
435
+ },
436
+
437
+ advanced: {
438
+ autoStartServer: true,
439
+ autoKillServer: true,
440
+ },
441
+
442
+ excludeFiles: [
443
+ '.vscode/',
444
+ '.git/',
445
+ // 'node_modules/', // ← 如需离线,请注释掉此行
446
+ 'dist/',
447
+ '*.log',
448
+ './yarn.lock',
449
+ ],
450
+
451
+ excludeDependencies: [
452
+ '@flun/desktop-builder',
453
+ ],
454
+
455
+ excludeOutputs: [
456
+ '*.blockmap',
457
+ 'latest.yml'
458
+ ],
459
+ };
460
+ ```
461
+
462
+ ---
463
+
464
+ ## 🌐 关于网络依赖与构建性能
465
+
466
+ ### 为什么默认排除 `node_modules`?
467
+
468
+ 在构建过程中,`electron-builder` 会对所有打包进去的文件进行数字签名(Windows 下为 Authenticode,macOS 下为 codesign),以确保应用未被篡改;
469
+ `node_modules` 目录通常包含成千上万个文件(尤其是大型项目),签名每个文件会耗费大量 CPU 和 I/O 时间,导致构建速度显著下降;
470
+
471
+ **更关键的是,包含 `node_modules` 会导致安装包体积暴增**(通常从几十 MB 涨到数百 MB),用户下载耗时、安装程序解压和复制数万个小文件的过程极其缓慢(尤其是在 Windows 上,NSIS 解压大量文件非常吃力);
472
+ 这会严重损害**用户安装体验**;
473
+
474
+ **因此,默认在 `excludeFiles` 中排除 `node_modules`,是经过深思熟虑的设计决策——优先保证构建速度和用户安装体验,让开发者能快速迭代,用户也能流畅安装;**
475
+
476
+ ### 默认行为下的网络需求
477
+
478
+ - 由于安装包不包含依赖,用户首次启动应用时会自动执行 `npm install`(或 `npm ci`)安装生产依赖;
479
+ - 此过程**需要联网**,并且依赖包数量越多,耗时越长;
480
+ - 但只需这一次,依赖安装完成后,后续启动完全离线,且运行性能与本地安装无异;
481
+
482
+ ### 如何实现完全离线运行?
483
+
484
+ 若用户网络环境受限,或您希望交付完全离线的安装包,只需在 `excludeFiles` 中**注释掉 `'node_modules/'`**,让依赖被打包;
485
+ 但请务必注意:
486
+ - **构建时间会增加**(复制、签名大量文件);
487
+ - **安装包体积会大幅增大**,用户安装时间也会变长;
488
+ - 权衡利弊,通常仅在以下情况建议包含依赖:
489
+ - 目标用户网络条件差;
490
+ - 应用依赖数量较少(< 50 个包),体积影响可控;
491
+
492
+ ### 优化建议(兼顾速度与离线)
493
+
494
+ 如果决定包含 `node_modules`,可以采取以下措施缓解性能问题:
495
+
496
+ 1. **精简依赖**:移除不必要的包,使用 `npm prune --production` 仅保留生产依赖,可将 `node_modules` 体积缩减 30%~50%;
497
+ 2. **使用 `build.asar: true`**:将 `node_modules` 打包成 ASAR 归档,减少文件数量,签名和安装时只需处理一个文件(但需测试兼容性,某些原生模块可能不兼容 ASAR);
498
+ 3. **排除无用文件**:在 `excludeFiles` 中添加模式,剔除 `node_modules` 中的测试、文档、示例等(例如 `node_modules/**/*.md`, `node_modules/**/test/` 等),进一步缩小体积;
499
+
500
+ **示例优化后的 `excludeFiles`(保留依赖,但剔除冗余文件):**
501
+
502
+ ```javascript
503
+ excludeFiles: [
504
+ '.vscode/',
505
+ '.git/',
506
+ // 保留 node_modules,但剔除无用文件
507
+ 'node_modules/**/*.md',
508
+ 'node_modules/**/test/',
509
+ 'node_modules/**/__tests__/',
510
+ 'node_modules/**/example/',
511
+ 'node_modules/**/examples/',
512
+ // ... 其他
513
+ ]
514
+ ```
515
+
516
+ **最佳组合方案(推荐):**
517
+
518
+ - 构建前执行 `npm prune --production`(移除开发依赖);
519
+ - 保留 `node_modules`,但只包含生产依赖,体积和文件数大大减少;
520
+ - 在 `package.json` 中设置 `scripts.prebuild` 和 `postbuild` 自动管理;
521
+
522
+ ```json
523
+ {
524
+ "scripts": {
525
+ "prebuild": "npm prune --production",
526
+ "build": "npx desktop-builder build",
527
+ "postbuild": "npm install"
528
+ }
529
+ }
530
+ ```
531
+
532
+ 这样既实现了离线,又通过精简依赖控制了构建和安装时间;
533
+
534
+ ---
535
+
536
+ ## 📌 进一步定制
537
+
538
+ 如果现有配置仍不能满足您的特殊需求,您可以通过以下方式进一步扩展:
539
+
540
+ ### 1. 直接使用 `electron-builder` 配置字段
541
+ `build` 对象中允许添加任何 `electron-builder` 官方支持的配置(如 `compression`、`extraResources`、`publish`、`afterPack` 等),它们会被正确合并到 `builder.json` 中;
542
+
543
+ ### 2. 使用钩子脚本
544
+ 通过设置 `build.afterPack` 或 `build.afterBuild` 等字段(指向项目中的脚本文件),可以在构建过程中执行自定义操作(例如复制额外文件、重新签名、上传到服务器);
545
+
546
+ ### 3. 修改主进程模板(高级)
547
+ 目前主进程由内置的 `electron-main.js` 模板生成;如需深度修改主进程逻辑,您可以使用 `patch-package` 对 `@flun/desktop-builder` 打补丁,或者 fork 项目并修改 `build.js` 以支持自定义模板路径(未来版本可能原生支持);
548
+
549
+ ### 4. 自行调用 `electron-builder`
550
+ 您也可以在 `package.json` 中编写自己的构建脚本,直接调用 `electron-builder` 并引用 `@flun/desktop-builder` 提供的临时构建目录,但这需要您自行管理复制、依赖安装等步骤;
551
+
552
+ **推荐路径**:优先尝试前两种(配置字段/钩子),如果仍不够,可向项目作者提交 Issue 或 PR 提出新增配置需求;
553
+
554
+ ---
555
+
556
+ ## 🛠️ 常见问题
557
+
558
+ ### 1. 构建时提示 `desktopAppConfig.js not found`
559
+ - 确认包已正确安装,`postinstall` 会自动复制模板;若未自动复制,可手动从 `node_modules/@flun/desktop-builder/desktopAppConfig.js` 复制到项目根目录;
560
+
561
+ ### 2. 构建失败,提示 `electron-builder` 相关错误
562
+ - 确保网络畅通,首次构建需下载 Electron 运行时(约 100MB);
563
+ - 可尝试设置镜像环境变量(构建脚本已自动配置国内镜像,如 `ELECTRON_MIRROR`);
564
+
565
+ ### 3. 应用版本号如何设置?
566
+ - 版本号取自项目根目录下 `package.json` 的 `version` 字段,请直接修改该文件;
567
+
568
+ ### 4. 生成的安装包很大(约 100MB)
569
+ - 正常,Electron 包含完整 Chromium 内核;可通过 `build.compression: 'maximum'` 或 `build.asar: true`(但包内 `asar` 默认为 `false` 以兼容某些后端)进行优化;
570
+
571
+ ### 5. 如何只生成当前平台的安装包?
572
+ - 默认行为即为只生成当前平台;如需生成其他平台,请在对应操作系统上执行构建命令;
573
+
574
+ ### 6. 菜单中的 `__TOGGLE_BROWSER__` 有什么作用?
575
+ - 该特殊标记会被替换为“在系统默认浏览器中打开应用地址”的功能,方便用户测试;
576
+
577
+ ### 7. 为什么我设置了 `nodeIntegration: false`,但应用仍然能访问 Node.js?
578
+ - 如上方“窗口配置”警告所述,本工具为了自动启动后端服务,**强制启用了 `nodeIntegration` 并关闭了 `contextIsolation` 和 `sandbox`**;
579
+ 这是设计上的必要妥协,但确实降低了安全性;**请勿在应用中加载外部网页或不可信内容**;
580
+
581
+ ### 8. 构建后的应用必须联网才能使用吗?
582
+ - **默认情况下**,首次启动需要联网安装依赖;之后可离线运行;
583
+ 若要完全离线,请在 `excludeFiles` 中保留 `node_modules`(注释掉排除规则),并考虑使用 `npm prune --production` 精简依赖,以平衡构建速度和安装体验;
584
+
585
+ ---
586
+
587
+ ## 📄 许可证
588
+
589
+ ISC © [flun](https://github.com/OpenFlun)
590
+
591
+ ---
592
+
593
+ ## 🤝 贡献
594
+
595
+ 欢迎提交 Issue 和 Pull Request;
596
+ 项目地址:[https://github.com/OpenFlun/desktop-builder](https://github.com/OpenFlun/desktop-builder)
package/copy-files.js ADDED
@@ -0,0 +1,34 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ // 要复制的文件位置和文件目标位置
6
+ const __filename = fileURLToPath(import.meta.url), __dirname = path.dirname(__filename),
7
+ fileName = 'desktopAppConfig.js', targetDir = path.resolve(__dirname, '../../..'),
8
+
9
+ // 要拷贝的文件和目标文件路径
10
+ sourceFile = path.join(__dirname, fileName), targetFile = path.join(targetDir, fileName);
11
+
12
+ /**
13
+ * 复制文件到项目根目录
14
+ * >查看定义:@see {@link copyFile}
15
+ * @returns {boolean} - 复制是否成功
16
+ */
17
+ const copyFile = () => {
18
+ console.log(`🔍 检查 ${fileName} 文件...`), console.log(`📁 项目根目录:${targetDir}`);
19
+ try {
20
+ if (fs.existsSync(targetFile)) return console.log('配置文件已存在,跳过创建;'), true; // 如果文件已存在,则跳过创建');
21
+ console.log(`⚠️ 在项目根目录未找到 ${fileName} 文件,正在创建...`);
22
+
23
+ fs.copyFileSync(sourceFile, targetFile); // 复制源文件到项目根目录
24
+ console.log(`✓ 已创建 ${fileName} 配置文件:${targetFile}`);
25
+ return true;
26
+ } catch (error) {
27
+ console.error(`✗ 创建 ${fileName} 文件失败:`, error.message);
28
+ return false;
29
+ }
30
+ }
31
+
32
+ // 执行脚本并导出函数
33
+ if (process.argv[1] === __filename) copyFile();
34
+ export { copyFile };