1. 从Cocos Creator到Windows桌面端:为什么值得折腾
很多做Cocos Creator的朋友,项目跑在浏览器或者模拟器里挺顺,一旦被问到“能不能给我一个双击就能打开的exe”,就开始挠头。尤其是做工具类、展示类、教育类小项目的团队,客户或者老板往往不关心你用了什么引擎,他们只想要一个Windows上能直接安装、桌面有快捷方式、卸载能在控制面板里找到的“正经软件”。这个需求听起来简单,但真动手做的时候,坑比想象中多。
我自己第一次把Cocos Creator项目打包成exe,是在一个展厅互动项目上。当时项目已经用Web Mobile构建跑通了,但现场要求断网运行、开机自启、全屏无边框,还要有一个安装向导。浏览器方案直接被否掉,因为现场人员不希望看到地址栏和标签页。于是我开始研究Electron加NSIS这条路,前后踩了大概两周的坑,才把整个链路跑顺。这篇文章就把这套流程完整拆开,从构建配置到Electron壳工程,再到NSIS安装包制作,每一步都讲清楚为什么这么做,以及我实际踩过哪些雷。
先明确一下这套方案适合谁:如果你用Cocos Creator 3.x做过项目,熟悉基本的构建发布流程,想让作品以原生Windows程序的形式交付,那这篇内容就是给你准备的。不需要你精通Node.js或者Windows底层,但需要你愿意动手改配置文件、跑命令行。整套流程的核心关键词就是Cocos Creator、exe、Windows、Electron、NSIS,我会围绕这五个点把每个环节讲透。
2. 整体方案设计与技术选型拆解
2.1 为什么是Electron而不是直接编译C++
Cocos Creator本身支持原生构建,理论上可以直接出Windows的可执行文件。但原生构建走的是C++工具链,需要Visual Studio的完整桌面开发环境,编译时间长,而且一旦项目里用了某些Web特有的API或者第三方JS库,移植起来非常痛苦。更关键的是,原生构建出来的窗口系统、菜单、安装包制作,都需要额外写C++代码去处理,对前端背景的开发者来说门槛太高。
Electron的思路完全不同。它本质上是一个自带Chromium内核和Node.js运行时的壳,你的Cocos Creator构建出来的Web产物直接塞进去就能跑。好处非常明显:构建产物是纯Web的,不需要改一行游戏逻辑代码;窗口管理、菜单、系统托盘、自动更新这些桌面端能力,Electron都有成熟的API;安装包制作有NSIS这种老牌工具,社区方案非常丰富。代价就是包体会大一些,一个空壳Electron大概70MB起步,加上你的项目资源,最终安装包可能到100MB以上。但对于大多数非3A级别的项目来说,这个体积完全可以接受。
2.2 构建产物格式的选择:Web Mobile还是Web Desktop
Cocos Creator在构建面板里提供了Web Mobile和Web Desktop两个选项。很多人会直觉选Web Desktop,觉得桌面端就应该用桌面端配置。但实际测试下来,Web Mobile的兼容性反而更好。原因是Web Desktop默认会启用一些针对桌面浏览器的优化,比如特定的输入事件处理,而Electron的Chromium版本和系统浏览器有差异,偶尔会出现鼠标事件偏移或者键盘映射不对的问题。Web Mobile的构建配置更保守,资源加载策略也更适合嵌入到壳里运行。
我一般建议这样配置:构建平台选Web Mobile,设备方向根据项目实际需求选,渲染后端优先用WebGL 2.0,如果目标机器比较老就降级到WebGL 1.0。资源压缩方面,如果项目里有大量图片,建议开启纹理压缩,但要注意Electron的Chromium对某些压缩格式的支持情况,最好在目标机器上实测一遍。构建完成后,你会得到一个包含index.html、assets目录和cocos-js目录的文件夹,这就是后面要嵌入Electron的完整产物。
2.3 Electron壳工程的最小化结构
Electron工程不需要多复杂,核心就三个文件:package.json、main.js和preload.js。package.json定义项目元信息和依赖,main.js是主进程入口,负责创建窗口和加载页面,preload.js用于在渲染进程和主进程之间安全地暴露接口。对于Cocos Creator项目来说,preload.js甚至可以暂时不用,因为游戏逻辑本身不需要和系统底层交互。但如果你要做全屏切换、读取本地配置文件、调用系统对话框,就需要通过preload.js来桥接。
目录结构建议这样组织:在Cocos Creator项目之外单独建一个文件夹作为Electron壳工程,里面放package.json和main.js,然后把Cocos Creator构建出来的web-mobile文件夹整个复制到壳工程的根目录下,命名为game或者www。这样主进程加载的时候直接指向这个文件夹里的index.html就行。分离的好处是Cocos Creator项目可以独立更新,重新构建后只需要替换game文件夹,不用动Electron的代码。
3. 核心细节解析与实操要点
3.1 Cocos Creator构建配置的隐藏细节
构建面板里有一个选项叫“MD5 Cache”,默认是勾选的。这个选项会给所有资源文件名加上哈希值,目的是解决浏览器缓存问题。但在Electron环境里,缓存问题不存在,因为每次都是本地加载。更麻烦的是,加了MD5之后,某些动态加载资源的路径可能会对不上,尤其是用了Asset Bundle的项目。我的建议是构建时取消勾选MD5 Cache,让文件名保持干净,减少路径解析出错的概率。
另一个容易忽略的是“首屏加载”相关的设置。Cocos Creator 3.x默认会有一个启动场景,构建后会生成一个splash screen。如果你希望exe启动时直接进入游戏,可以在构建配置里把启动场景设置好,并且关闭“显示FPS”之类的调试选项。还有“远程服务器地址”这一项,如果项目里没有用到远程资源,一定要留空,否则构建产物会尝试去请求一个不存在的地址,导致启动卡住。
构建完成后,打开生成的index.html,检查一下里面的资源引用路径。正常情况下应该是相对路径,比如./cocos-js/xxx.js。如果看到以斜杠开头的绝对路径,说明构建配置里的“资源服务器地址”被填了东西,需要清空后重新构建。这个细节很关键,因为Electron加载本地文件时,绝对路径会指向文件系统的根目录,直接导致白屏。
3.2 Electron主进程的关键参数配置
main.js里创建窗口的时候,有几个参数直接决定了用户体验。首先是width和height,建议设置成项目设计分辨率,比如1280x720或者1920x1080。然后是fullscreen,如果要做全屏无边框,可以设置fullscreen: true和frame: false,但要注意这样用户就没法通过标题栏关闭窗口了,需要自己加一个退出快捷键或者菜单。我一般会保留frame,但设置autoHideMenuBar: true,这样菜单栏默认隐藏,按Alt键才显示,既干净又不影响调试。
webPreferences里的配置更需要小心。nodeIntegration必须设为false,contextIsolation必须设为true,这是Electron的安全基线。很多老教程会让你把nodeIntegration设为true,那样确实方便,渲染进程里直接能用Node.js的API,但这也意味着如果游戏里加载了恶意脚本,就能直接操作你的文件系统。正确做法是通过preload.js暴露有限的接口,比如一个quitApp方法或者toggleFullscreen方法,让渲染进程按需调用。
还有一个参数叫backgroundColor,建议设置成黑色或者项目的主色调。因为Electron加载页面需要时间,如果背景是白色,启动瞬间会闪一下白屏,体验很差。设置成深色背景后,视觉上会平滑很多。另外show: false配合ready-to-show事件也是常用技巧,等页面完全加载好再显示窗口,避免看到加载过程中的空白。
3.3 NSIS脚本的核心逻辑与参数计算
NSIS的安装脚本看起来像天书,但核心逻辑其实不复杂。一个标准的安装包需要做几件事:欢迎页面、选择安装目录、复制文件、创建快捷方式、写入注册表卸载信息、完成页面。NSIS用脚本语言描述这些步骤,每个步骤对应一个指令或者一个宏。
安装目录的默认值一般设为$PROGRAMFILES64\你的应用名,如果是32位程序就用$PROGRAMFILES。这里有个坑:如果你的Electron是64位的,但NSIS编译出来的安装包默认是32位,安装到64位系统时路径会不对。解决办法是在NSIS脚本开头加上!include "x64.nsh",然后用${If} ${RunningX64}来判断系统架构,分别设置不同的安装目录。
文件复制用File /r指令,把整个Electron打包后的文件夹递归复制到安装目录。注意路径分隔符要用反斜杠,而且源路径是相对于NSIS脚本文件的。创建快捷方式用CreateShortCut指令,桌面快捷方式和开始菜单快捷方式各创建一个。卸载信息写入注册表HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\你的应用名,这样控制面板里才能看到卸载入口。写入的时候需要设置DisplayName、UninstallString、DisplayIcon这几个键值,缺一不可。
3.4 图标与版本信息的嵌入方式
Electron打包出来的exe默认是Electron的图标,任务栏和文件管理器里看起来很不专业。替换图标需要用到一个工具叫rcedit,它可以直接修改exe文件的资源段。安装方式很简单,npm install rcedit --save-dev,然后在打包脚本里调用它。需要准备一个.ico格式的图标文件,里面最好包含16x16、32x32、48x48、256x256多个尺寸,这样在不同场景下显示都清晰。
版本信息的嵌入也是通过rcedit完成的。可以设置FileDescription、ProductName、CompanyName、LegalCopyright、FileVersion、ProductVersion这些字段。这些信息会显示在文件属性的详细信息标签页里,虽然用户不常看,但有没有这些信息,给人的专业感差别很大。特别是FileVersion,如果后续要做自动更新,版本号比对就靠它。
4. 完整实操流程与关键环节实现
4.1 环境准备与依赖安装
先确认本机已经安装了Node.js,版本建议在16以上。然后全局安装Electron和electron-builder,后者虽然我们不一定用它的打包功能,但它的依赖管理做得很好,可以省去很多手动配置。命令是npm install -g electron electron-builder。如果网络环境不好,可以配置淘宝镜像,npm config set registry https://registry.npmmirror.com。
NSIS需要单独安装,去官网下载最新版,安装时勾选“NSIS Language Files”和“Install NSIS Plugins”。安装完成后,把NSIS的安装目录添加到系统环境变量Path里,这样命令行才能直接调用makensis命令。验证安装是否成功,可以在命令行输入makensis /VERSION,如果输出版本号就说明配置好了。
Cocos Creator这边,确保项目已经能正常构建Web Mobile。在构建面板里,平台选Web Mobile,构建路径选一个单独的文件夹,比如build/web-mobile。构建完成后,打开build/web-mobile/index.html,用浏览器直接打开,确认游戏能正常运行。这一步很重要,如果浏览器里都跑不起来,嵌入Electron之后更不可能跑起来。
4.2 Electron壳工程的搭建与调试
新建一个文件夹叫electron-shell,在里面执行npm init -y生成package.json。然后修改package.json,添加main字段指向main.js,添加scripts里的start命令为electron .。接着安装Electron依赖,npm install electron --save-dev。如果之前全局安装过,这里也可以直接用全局的,但建议项目内安装,版本可控。
创建main.js,写入窗口创建逻辑。核心代码大概是这样:
const { app, BrowserWindow, Menu } = require('electron'); const path = require('path'); function createWindow() { const win = new BrowserWindow({ width: 1280, height: 720, backgroundColor: '#000000', show: false, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }); win.loadFile(path.join(__dirname, 'game', 'index.html')); win.once('ready-to-show', () => { win.show(); }); } app.whenReady().then(createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } });把Cocos Creator构建出来的web-mobile文件夹复制到electron-shell目录下,重命名为game。然后在命令行执行npm start,如果一切正常,应该能看到一个窗口打开,里面运行着你的游戏。如果白屏,按F12打开开发者工具,看Console里报什么错。常见错误是资源路径不对,检查index.html里的引用是不是相对路径。
4.3 使用electron-builder生成可执行文件
虽然可以直接用Electron运行,但交付给用户的时候不能要求他们装Node.js和Electron。需要用electron-builder把整个工程打包成一个独立的exe。在package.json里添加build字段,配置如下:
"build": { "appId": "com.yourcompany.yourgame", "productName": "YourGame", "directories": { "output": "dist" }, "win": { "target": "dir", "icon": "build/icon.ico" } }这里target设为dir,意思是只生成文件夹形式的可执行文件,不生成安装包。因为安装包我们后面用NSIS自己做,这样更灵活。执行npx electron-builder --win,等待打包完成。在dist目录下会生成一个win-unpacked文件夹,里面有一个YourGame.exe,双击就能运行。这个文件夹就是后面NSIS要打包的源文件。
打包过程中可能会遇到下载Electron二进制包很慢的问题。可以在项目根目录建一个.npmrc文件,写入electron_mirror=https://npmmirror.com/mirrors/electron/,这样下载速度会快很多。如果还是失败,可以手动下载对应的zip包,放到缓存目录里。缓存目录一般在%LOCALAPPDATA%\electron\Cache,把下载好的zip放进去,重新执行打包命令即可。
4.4 NSIS安装包脚本编写与编译
新建一个文件叫installer.nsi,用记事本或者VS Code打开。脚本开头定义应用名称、版本号、安装目录等变量:
!define APP_NAME "YourGame" !define APP_VERSION "1.0.0" !define APP_PUBLISHER "YourCompany" !define APP_EXE "YourGame.exe" !define INSTALL_DIR "$PROGRAMFILES64\${APP_NAME}"然后引入必要的头文件,MUI2.nsh提供现代界面,x64.nsh提供64位检测,FileFunc.nsh提供文件操作函数。接着定义安装页面,一般保留欢迎页、目录选择页、安装进度页和完成页。安装逻辑里,先用SetOutPath设置输出目录,然后File /r复制文件。复制完成后创建快捷方式:
CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "${INSTALL_DIR}\${APP_EXE}" CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "${INSTALL_DIR}\${APP_EXE}"写入注册表卸载信息:
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayName" "${APP_NAME}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "UninstallString" "${INSTALL_DIR}\uninstall.exe" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayIcon" "${INSTALL_DIR}\${APP_EXE}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayVersion" "${APP_VERSION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "Publisher" "${APP_PUBLISHER}"卸载逻辑里,删除安装目录、删除快捷方式、删除注册表项。注意卸载程序本身也在安装目录里,所以删除目录的时候要先把卸载程序自己复制到临时目录再执行,否则会报“文件正在使用”的错误。NSIS提供了Uninstall相关的宏来处理这个,但手动写的话,可以用CopyFiles把uninstall.exe复制到$TEMP,然后ExecWait执行它。
编译命令是makensis installer.nsi,如果脚本没有语法错误,会在当前目录生成一个Setup.exe。这个就是最终的安装包,双击后会弹出安装向导,选择目录、点击下一步、完成安装。安装完成后桌面会出现快捷方式,控制面板里也能看到卸载入口。
5. 常见问题与排查技巧实录
5.1 启动白屏与资源加载失败
白屏是最高频的问题,没有之一。排查思路分三步:第一步,在Electron窗口里按F12打开开发者工具,看Console有没有报错。如果是Failed to load resource,说明路径不对。检查index.html里的<script>标签,看src是不是以./开头。如果是/开头,去Cocos Creator构建配置里把“资源服务器地址”清空,重新构建。
第二步,如果Console没有报错但页面还是白的,检查main.js里loadFile的路径对不对。可以用path.join(__dirname, 'game', 'index.html')来拼接,确保路径是绝对路径。如果路径里有中文或者空格,Electron有时候会解析失败,建议把工程目录改成纯英文无空格的路径。
第三步,如果以上都没问题,可能是Cocos Creator的启动场景没有正确加载。打开构建产物里的index.html,看里面有没有<div id="GameDiv">或者类似的容器。如果没有,说明构建配置里没有设置启动场景,回到Cocos Creator的构建面板,在“启动场景”下拉框里选一个场景,重新构建。
5.2 NSIS编译报错与安装失败
NSIS报错信息通常比较晦涩,但常见的就那么几种。Invalid command: xxxx一般是拼写错误或者缺少头文件,检查对应的指令是不是写错了,或者有没有!include对应的nsh文件。File: failed opening file是文件路径不对,检查File /r后面的路径是不是相对于nsi脚本文件的,如果不在同一目录,需要用绝对路径或者..\来跳转。
安装失败最常见的原因是权限不足。如果安装目录设在$PROGRAMFILES64,而安装包没有请求管理员权限,写入会失败。解决办法是在nsi脚本开头加上RequestExecutionLevel admin,这样安装时会弹出UAC提示,用户同意后才能继续。另一个原因是文件被占用,比如之前安装过旧版本,旧版本的进程还在运行,导致新文件覆盖不了。可以在安装前加一个检测进程的步骤,如果发现进程在运行就提示用户先关闭。
还有一个坑是NSIS的默认压缩算法。如果安装包体积很大,编译时间会很长,而且生成的安装包可能超过2GB,导致某些系统无法正常读取。可以在脚本里设置SetCompressor /SOLID lzma,这是压缩率最高的算法,但编译最慢。如果追求速度,可以用SetCompressor zlib,压缩率低一些但快很多。我一般用lzma,因为安装包体积小对用户更友好。
5.3 Electron版本与Cocos Creator的兼容性
Electron的版本更新很快,但并不是越新越好。Cocos Creator 3.x的WebGL渲染对Chromium版本有一定要求,太老的Electron可能不支持某些WebGL扩展,太新的又可能有API变动。我实测下来,Electron 22到25这个区间比较稳,对应的Chromium版本在108到114之间,对WebGL 2.0的支持很完整。
如果项目里用了物理引擎或者粒子系统,建议在目标Electron版本上先跑一遍性能测试。有时候在浏览器里跑60帧,到了Electron里只有30帧,原因是Electron默认开启了垂直同步,而某些显卡驱动对垂直同步的处理不一样。可以在main.js里加app.commandLine.appendSwitch('disable-frame-rate-limit')来解除帧率限制,但这样可能会导致画面撕裂,需要根据实际情况权衡。
5.4 安装包体积优化与启动速度提升
安装包体积主要来自三部分:Electron运行时、Cocos Creator的引擎代码、项目资源。Electron运行时大概70MB,这个没法压缩太多,但可以在electron-builder配置里排除一些不需要的语言包和调试文件。Cocos Creator的引擎代码可以通过构建时的“引擎分离”选项来减小,只打包项目实际用到的模块。项目资源方面,图片压缩和音频压缩是最有效的,纹理压缩格式选对也能省不少空间。
启动速度方面,Electron加载页面需要时间,如果项目资源多,首屏加载可能好几秒。优化手段包括:开启Cocos Creator的“预加载”功能,把首屏需要的资源提前加载;在Electron的main.js里设置show: false,等ready-to-show再显示窗口,避免白屏;把不重要的资源改成远程加载或者延迟加载。实测下来,一个中等规模的项目,优化后启动时间能从5秒降到2秒左右。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 启动白屏 | 资源路径错误 | F12看Console报错 | 检查index.html引用路径,清空构建配置里的服务器地址 |
| 窗口闪退 | 主进程报错 | 命令行运行看输出 | 检查main.js语法,确保loadFile路径正确 |
| 安装失败 | 权限不足 | 看安装日志 | nsi脚本加RequestExecutionLevel admin |
| 快捷方式无效 | 路径含空格 | 右键属性看目标 | 安装目录避免空格,或用引号包裹路径 |
| 卸载残留 | 注册表未清理 | 控制面板看条目 | 检查卸载脚本里的DeleteRegKey指令 |
| 帧率低 | 垂直同步 | 对比浏览器表现 | 加disable-frame-rate-limit开关 |
| 图标不显示 | ico格式不对 | 文件属性看图标 | 用多尺寸ico,rcedit重新嵌入 |
| 安装包过大 | 未压缩资源 | 看各文件夹体积 | 开启纹理压缩,排除Electron多余文件 |
6. 进阶技巧与个人经验分享
6.1 自动更新方案的轻量实现
如果项目需要频繁更新,每次让用户重新下载安装包体验很差。Electron内置了autoUpdater模块,但需要搭配一个更新服务器。轻量做法是:在安装目录下放一个version.json文件,记录当前版本号。程序启动时请求远程服务器上的version.json,比对版本号,如果有新版本就下载增量包或者完整包,然后调用NSIS的静默安装参数/S来覆盖安装。这套方案不需要复杂的后端,一个静态文件服务器就够了。
需要注意的是,自动更新涉及文件替换,如果程序正在运行,文件会被占用。解决办法是更新程序单独做一个exe,主程序检测到新版本后启动更新程序,然后主程序退出,更新程序等待几秒后替换文件,再重新启动主程序。这个逻辑用Node.js的child_process模块就能实现,不需要额外的框架。
6.2 多分辨率适配与窗口模式切换
Cocos Creator的项目设计分辨率是固定的,但用户的显示器千奇百怪。Electron窗口创建时可以设置useContentSize: true,这样窗口大小就是内容区域大小,不受边框影响。然后在Cocos Creator里开启“适配屏幕宽度”或者“适配屏幕高度”,让游戏画面自动缩放。如果要做全屏切换,可以在preload.js里暴露一个toggleFullscreen方法,渲染进程通过按钮触发,主进程调用win.setFullScreen(!win.isFullScreen())。
窗口模式方面,除了普通窗口和全屏,还可以做无边框窗口。无边框窗口需要自己实现拖动和关闭按钮,拖动可以通过CSS的-webkit-app-region: drag来实现,关闭按钮调用win.close()。这种模式适合做展示类或者工具类应用,看起来更现代。但要注意无边框窗口下,用户没法通过系统菜单关闭,必须提供显眼的退出入口。
6.3 日志记录与崩溃分析
Electron程序崩溃时,默认不会留下太多线索。可以在main.js里监听uncaughtException事件,把错误堆栈写入本地日志文件。日志文件放在app.getPath('userData')目录下,这个目录在Windows上一般是%APPDATA%\你的应用名。写入的时候用fs.appendFileSync,确保崩溃瞬间也能写进去。日志内容包含时间戳、错误信息、Electron版本、系统版本,方便后续排查。
如果崩溃发生在渲染进程,可以在preload.js里监听window.onerror,把错误信息通过IPC发送到主进程,再由主进程写入日志。IPC通信用ipcRenderer.send和ipcMain.on,注意contextIsolation开启后,preload.js里不能直接用Node.js的fs模块,需要通过contextBridge.exposeInMainWorld暴露一个日志方法给渲染进程调用。
6.4 安装包签名与用户信任
没有签名的exe在Windows上运行时会弹出SmartScreen警告,提示“Windows已保护你的电脑”。虽然用户可以点“仍要运行”,但体验很差,而且有些企业环境直接禁止运行未签名的程序。解决办法是购买代码签名证书,用signtool对exe和安装包进行签名。签名命令是signtool sign /f cert.pfx /p password /t http://timestamp.digicert.com YourGame.exe,时间戳服务器用DigiCert的免费服务就行。
代码签名证书有OV和EV两种,OV便宜但需要积累信誉才能消除SmartScreen警告,EV贵但立即生效。如果项目是内部使用,可以跳过签名,但要在文档里说明如何绕过SmartScreen。如果是商业交付,建议至少买OV证书,并且对主程序和安装包都签名。签名之后,文件属性里会多一个“数字签名”标签页,用户看到这个会放心很多。
6.5 我踩过的最大的三个坑
第一个坑是路径中的中文。早期项目放在D:\项目\游戏这样的目录下,Electron加载时一直白屏,Console里报ERR_FILE_NOT_FOUND。排查了半天才发现是中文路径导致URL编码问题。后来把所有工程目录改成纯英文,问题消失。这个坑的教训是:从Cocos Creator构建到Electron打包,整条链路都尽量用英文路径,避免不必要的编码问题。
第二个坑是NSIS的卸载程序自删除。第一次写卸载脚本时,直接RMDir /r $INSTALL_DIR,结果卸载程序自己也在那个目录里,执行到一半文件被删了,卸载中断。正确做法是先把uninstall.exe复制到$TEMP目录,然后ExecWait执行临时目录里的卸载程序,原目录里的文件就可以安全删除了。这个逻辑在NSIS官方文档里有示例,但第一次写很容易忽略。
第三个坑是Electron的缓存目录。Electron默认会把Chromium的缓存写到%APPDATA%下,如果用户频繁安装卸载,缓存目录会残留,导致新版本启动时加载了旧缓存,出现奇怪的问题。解决办法是在main.js里设置app.setPath('userData', path.join(app.getPath('temp'), 'YourApp')),把用户数据目录指向临时文件夹,这样每次启动都是干净的。但这样做的代价是用户配置不会保留,需要根据实际需求权衡。
7. 交付前的检查清单与实用建议
在把安装包发给用户之前,建议在一台干净的Windows机器上完整测试一遍。测试内容包括:双击安装包能否正常启动向导;选择非默认目录安装是否成功;桌面和开始菜单快捷方式是否创建;双击快捷方式能否启动程序;程序功能是否正常;控制面板卸载是否干净;卸载后安装目录是否残留文件。这七个步骤走一遍,基本能覆盖90%的问题。
另外建议在安装包里附一个readme.txt,写明最低系统要求、安装步骤、常见问题联系方式。虽然用户大概率不会看,但有了这个文件,显得更正规。如果项目是商业交付,还可以在安装完成页面加一个“访问官网”的勾选项,用NSIS的ExecShell指令打开浏览器。这些细节不影响功能,但能提升整体质感。
最后说一个实用建议:把整个打包流程脚本化。写一个build.bat,里面依次执行Cocos Creator的命令行构建、复制文件到Electron壳、electron-builder打包、makensis编译安装包。这样每次发版只需要改一下版本号,双击bat就能生成最终的Setup.exe,省去大量重复操作。Cocos Creator支持命令行构建,命令是CocosCreator.exe --project 项目路径 --build "platform=web-mobile",具体参数可以参考官方文档。脚本化之后,整个打包过程从原来的半小时缩短到五分钟,而且不容易出错。