最近想要制作一个 Windows 工具箱,所以需要多集合一些功能。之前用 uniapp 制作了一些功能,为了省事,所以想要把部分 uniapp 封装成 exe 来丰富功能。
看了一下,由于 uniapp 并未提供打包 exe 的方法,所以需要借助 electron 来对编译后的内容进行打包。
最近萌生了制作一个 Windows 工具箱 的想法,希望它能整合多种实用功能,方便日常使用。由于之前用 UniApp 制作了一些工具,为了节省开发时间和重复工作量,我决定将部分 UniApp 项目封装为 EXE 文件,以丰富工具箱的功能。
UniApp 打包 EXE 的限制
UniApp 是一个强大的跨平台开发框架,支持多平台(如 H5、小程序、App)的快速开发,但目前官方并未提供直接打包成 Windows EXE 的方法。因此,我们需要借助其他工具实现这一目标。在调研过程中发现,Electron 是一个很适合的选择。
为什么选择 Electron?
Electron 是一个用于构建跨平台桌面应用的框架,基于 Chromium 和 Node.js,允许使用 Web 技术(如 HTML、CSS 和 JavaScript)构建桌面应用。以下是它的一些优势:
- 易用性:Electron 的生态成熟,能够轻松加载 HTML 文件或 Web 项目。
- 兼容性强:支持 Windows、macOS 和 Linux,开发一次即可多平台运行。
- 与 UniApp 结合性:可以将 UniApp 项目的 H5 版本嵌入 Electron,轻松实现功能扩展。
项目实现步骤
接下来简单讲一下使用 Electron 将 UniApp 封装为 EXE 的具体流程:
1. 准备 UniApp 项目
首先,需要将 UniApp 项目构建为 H5 版本。步骤如下:
- 打开 HBuilderX,加载你的 UniApp 项目。
- 点击菜单栏 发行 -> 网站(H5)。
- 等待构建完成后,在项目目录中会生成一个
dist
文件夹,其中包含 H5 的静态文件。
2. 创建 Electron 项目
安装 Node.js 环境后(默认大家都安装了),按照以下步骤创建一个 Electron 项目:
1、初始化项目:
准备一个正常可以打包成 web 的正常 uniapp 项目
2、安装 Electron:
npm install electron --save-dev
安装出错了,报了以下错误,看起来像是连接超时了,换了几次源发现都不行,查资料发现安装 Electron 时需要安装 Github 内容,下载不全才导致的。
C:\Users\Administrator.DESKTOP-8NNEK6T>npm install -g electron
npm warn deprecated boolean@3.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
npm warn cleanup Failed to remove some directories [
npm warn cleanup [
npm warn cleanup 'C:\\Users\\Administrator.DESKTOP-8NNEK6T\\AppData\\Roaming\\npm\\node_modules\\electron',
npm warn cleanup [Error: EPERM: operation not permitted, rmdir 'C:\Users\Administrator.DESKTOP-8NNEK6T\AppData\Roaming\npm\node_modules\electron\node_modules\decompress-response'] {
npm warn cleanup errno: -4048,
npm warn cleanup code: 'EPERM',
npm warn cleanup syscall: 'rmdir',
npm warn cleanup path: 'C:\\Users\\Administrator.DESKTOP-8NNEK6T\\AppData\\Roaming\\npm\\node_modules\\electron\\node_modules\\decompress-response'
npm warn cleanup }
npm warn cleanup ],
npm warn cleanup [
npm warn cleanup '\\\\?\\C:\\Users\\Administrator.DESKTOP-8NNEK6T\\AppData\\Roaming\\npm\\node_modules\\electron\\node_modules',
npm warn cleanup [Error: EPERM: operation not permitted, rmdir 'C:\Users\Administrator.DESKTOP-8NNEK6T\AppData\Roaming\npm\node_modules\electron\node_modules\global-agent'] {
npm warn cleanup errno: -4048,
npm warn cleanup code: 'EPERM',
npm warn cleanup syscall: 'rmdir',
npm warn cleanup path: 'C:\\Users\\Administrator.DESKTOP-8NNEK6T\\AppData\\Roaming\\npm\\node_modules\\electron\\node_modules\\global-agent'
npm warn cleanup }
npm warn cleanup ]
npm warn cleanup ]
npm error code 1
npm error path C:\Users\Administrator.DESKTOP-8NNEK6T\AppData\Roaming\npm\node_modules\electron
npm error command failed
npm error command C:\WINDOWS\system32\cmd.exe /d /s /c node install.js
npm error RequestError: connect ETIMEDOUT 20.205.243.166:443
npm error at ClientRequest.<anonymous> (C:\Users\Administrator.DESKTOP-8NNEK6T\AppData\Roaming\npm\node_modules\electron\node_modules\got\dist\source\core\index.js:970:111)
npm error at Object.onceWrapper (node:events:633:26)
npm error at ClientRequest.emit (node:events:530:35)
npm error at origin.emit (C:\Users\Administrator.DESKTOP-8NNEK6T\AppData\Roaming\npm\node_modules\electron\node_modules\@szmarczak\http-timer\dist\source\index.js:43:20)
npm error at emitErrorEvent (node:_http_client:103:11)
npm error at TLSSocket.socketErrorListener (node:_http_client:506:5)
npm error at TLSSocket.emit (node:events:518:28)
npm error at emitErrorNT (node:internal/streams/destroy:170:8)
npm error at emitErrorCloseNT (node:internal/streams/destroy:129:3)
npm error at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
npm error at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1610:16)
npm error A complete log of this run can be found in: C:\Users\Administrator.DESKTOP-8NNEK6T\AppData\Local\npm-cache\_logs\2024-12-31T08_52_55_131Z-debug-0.log
第一种方法就是设置代理,第二种方法就是单独设置 ELECTRON_MIRROR
环境变量:
步骤(无问题跳过):
1. 设置临时环境变量
在 PowerShell 中设置环境变量 ELECTRON_MIRROR
,指向国内镜像地址。打开 PowerShell 窗口并执行以下命令:
$env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
这个会在 PowerShell 会话中临时设置 ELECTRON_MIRROR
环境变量。
2. 安装 Electron
然后你可以执行以下命令来安装 Electron:
npm install --save-dev electron
这样 Electron 安装就能走国内的镜像源,而不是默认的 GitHub 源,从而减少因网络问题导致的安装失败。
3、大致结构:
打包后的内容在 unpackage/dist/build/web/
下,初始结构包括 index.html
,assets 目录以及 static 目录,需要创建你 main.js
以及 package.json
并补全相关内容即可。
4、编写 main.js
文件:
const {
app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
});
// 加载 UniApp 打包后的文件
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// 开启开发者工具(可选)
// mainWindow.webContents.openDevTools();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
5、编写 package.json
在 web 目录下新建 package.json
(npm)文件
简单修改内容 package.json
内容,修改作者
{
"name": "进制计算器",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"electron": "^23.1.0"
},
"author": "繁依Fanyi",
"license": "ISC"
}
3. 打包为 EXE
完成 Electron 项目后,我们需要将其打包为 EXE 文件:
1、安装打包工具 electron-packager:
npm install electron-packager --save-dev
2、执行打包命令:
npx electron-packager . my-toolbox --platform=win32 --arch=x64 --out=release-build --overwrite
my-toolbox 是打包后的二进制 exe 名称,而不是应用上方显示的名称
想要修改这个名称,可以在WEB发行时修改网站标题即可
打包的时候可能会出现找不到包的情况 can't found module xxx .... from 某某路径
,这时候可以把找不到的包写在 package.json
中的 devDependences 下配置,我这里是找不到 electron,所以就直接配置了 electron,然后 npm install
安装依赖即可。
打包过程中也可能会出现 connect ETIMEDOUT 20.205.243.166:443
的问题,所以我还是建议直接把 $env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
配置到环境变量中。
3、打包成功后,release-build
文件夹中会生成 my-toolbox.exe
文件,双击即可运行。
如果打包后内容空白,可能是打包时没有配置 manifest.json
中的基础路径,我是自己写的小应用,https也取消了
设置基础路径为 ./
,保存后重新打包 h5 就行了。
打包成功后就是这样了
打包exe后的内容如下,点击 exe 即可运行。
4. 优化和注意事项
- 静态资源加载问题:确保文件夹完整无误地放在项目根目录。
- 打包大小优化:Electron 打包的文件可能较大,可以使用压缩工具(如
electron-builder
)进一步优化。 - 功能扩展:可以在 Electron 中添加更多桌面功能(如系统托盘、文件操作等),以增强工具箱的实用性。
- 样式优化:编写相关参数优化窗口大小,样式等来进一步美化。
1、窗口优化
首先时窗口大小,宽屏不太适合这个比较长的计算器,所以需要限制窗口大小为 600 * 1000 左右范围,设置范围内等比缩放,隐藏顶部菜单栏:
const {
app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 300, // 初始宽度
height: 600, // 初始高度
minWidth: 300, // 最小宽度
minHeight: 600, // 最小高度
maxWidth: 1200, // 最大宽度
maxHeight: 2000, // 最大高度
webPreferences: {
nodeIntegration: true,
},
autoHideMenuBar: true, // 隐藏菜单栏
// 如果不想让鼠标点击窗口顶部区域时自动显示菜单栏,可以加上下面的代码
// hideMenuBar: true,
});
// 加载 UniApp 打包后的文件
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// 设置初始宽高比为 0.5
mainWindow.setAspectRatio(0.5);
// 开启开发者工具(可选)
// mainWindow.webContents.openDevTools();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
2、滚动条优化
如果希望完全隐藏滚动条,可以在 index.html
的 <style>
部分添加以下 CSS:
/* 隐藏所有滚动条 */
body {
overflow: hidden;
}
如果只是希望样式优化,而不是完全隐藏,可以调整滚动条的外观,例如:
/* 优化滚动条样式 */
::-webkit-scrollbar {
width: 6px; /* 滚动条宽度 */
}
::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.3); /* 滚动条颜色 */
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(0, 0, 0, 0.5); /* 滚动条悬停颜色 */
}
3、更改程序图标:
在 Electron 中更换应用程序的图标非常简单。你可以通过在创建 BrowserWindow
和 app
实例时指定图标路径来设置图标。下面我将给你展示如何为 Windows 和 macOS 更换应用程序图标。
1. 更换应用程序图标(Windows)
在 Windows 系统中,图标通常使用 .ico
格式。你可以在创建 BrowserWindow
或 app
时指定图标路径。
- 准备一个
.ico
格式的图标文件。 - 在
BrowserWindow
或app
创建时,使用icon
属性指定图标路径。
const {
app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
icon: path.join(__dirname, 'icon.ico'), // 设置图标
});
// 加载 UniApp 打包后的文件
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// 如果需要开发者工具,可以开启
// mainWindow.webContents.openDevTools();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
icon: path.join(__dirname, 'icon.ico')
这行代码是设置图标的关键,icon.ico
应该是你放置在项目目录中的图标文件。
2. 更换应用程序图标(macOS)
在 macOS 上,图标通常使用 .icns
格式,而不仅仅是 .ico
格式。你可以使用类似的方法来设置图标,但需要使用 .icns
文件。
- 准备一个
.icns
格式的图标文件。 - 使用
app.dock.setIcon()
来设置 macOS 系统中应用程序的图标。
const {
app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
icon: path.join(__dirname, 'icon.icns'), // macOS 图标
});
// 设置应用程序图标(macOS)
app.dock.setIcon(path.join(__dirname, 'icon.icns'));
// 加载 UniApp 打包后的文件
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// 如果需要开发者工具,可以开启
// mainWindow.webContents.openDevTools();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.dock.setIcon()
用于设置 macOS 的 dock 图标。
3. 更换打包后的应用程序图标
如果你打包应用程序后,还想更换最终生成的安装包图标,你需要在打包配置中指定图标。这里以 Electron Builder 和 Electron Packager 为例。
使用 Electron Packager
在使用 electron-packager
打包时,可以使用 --icon
参数指定图标文件路径。图标的格式可以是 .ico
(Windows)或者 .icns
(macOS)。
electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --overwrite --icon=icon.ico
--icon=icon.ico
用来设置图标。
使用 Electron Builder
在 electron-builder
配置中,你可以在 package.json
或者单独的 electron-builder
配置文件中指定图标路径。
示例:在 package.json
中配置图标
{
"name": "my-app",
"version": "1.0.0",
"build": {
"appId": "com.example.myapp",
"mac": {
"icon": "icon.icns" // macOS 图标
},
"win": {
"icon": "icon.ico" // Windows 图标
}
}
}
- 在上面的配置中,
mac.icon
用来设置 macOS 图标,win.icon
用来设置 Windows 图标。
然后,你可以使用 electron-builder
来打包应用:
electron-builder
4. 注意事项
- Windows 图标:Windows 系统推荐使用
.ico
格式的图标。你可以使用在线工具(如 ICO Converter)将其他格式的图像转换为.ico
格式。 - macOS 图标:macOS 使用
.icns
格式的图标。你可以使用 macOS 自带的iconutil
工具或者在线工具将其他格式的图像转换为.icns
格式。 - Linux 图标:Linux 系统通常支持
.png
或.svg
格式的图标。
5. electron-packager 打包内容补充
electron-packager
是一个常用的命令行工具,用于将 Electron 应用打包成可执行文件。它可以将你的应用程序打包为适用于不同平台(Windows、macOS 和 Linux)的安装包。
以下是 electron-packager
常用命令和参数的说明:
基本命令
electron-packager <应用目录> <应用名称> --platform=<平台> --arch=<架构> --out=<输出目录>
常用参数
-
应用目录 (
<应用目录>
):- 应用的源代码目录,通常是你的项目根目录。
-
应用名称 (
<应用名称>
):- 打包后的应用程序名称。你可以为打包的应用指定一个名称,通常会使用项目名称。
-
–platform (
<平台>
):- 指定打包的目标平台。可选值包括:
win32
: Windowsdarwin
: macOSlinux
: Linux
- 例:
--platform=win32
- 指定打包的目标平台。可选值包括:
-
–arch (
<架构>
):- 指定打包的目标架构。常见的架构有:
x64
: 64 位ia32
: 32 位armv7l
: ARM(树莓派等设备)arm64
: ARM 64 位
- 例:
--arch=x64
- 指定打包的目标架构。常见的架构有:
-
–out (
<输出目录>
):- 指定打包后的文件输出目录。所有生成的文件将保存在此目录下。
- 例:
--out=release-build
-
–overwrite:
- 如果输出目录中已有打包文件,使用该选项时会覆盖已有文件。
- 例:
--overwrite
-
–asar:
- 将应用的资源打包成 ASAR(Atom Shell Archive)文件。默认情况下,Electron 会将应用的代码和资源存储为文件夹格式,使用
--asar
选项可以将其压缩为单个 ASAR 文件。 - 例:
--asar
- 将应用的资源打包成 ASAR(Atom Shell Archive)文件。默认情况下,Electron 会将应用的代码和资源存储为文件夹格式,使用
-
–icon (
<图标文件>
):- 为打包的应用指定一个图标。支持
.ico
、.png
等格式。常用于 Windows 和 macOS 上的应用图标。 - 例:
--icon=path/to/icon.ico
- 为打包的应用指定一个图标。支持
-
–prune:
- 在打包时剔除项目中的开发依赖。对于生产环境打包应用时通常需要使用该选项,以减小最终打包文件的大小。
- 例:
--prune
-
–ignore (
<路径>
):- 指定打包时忽略某些文件或目录。支持 glob 模式(类似于文件路径匹配)。常用于排除不必要的文件。
- 例:
--ignore="tests/*"
-
–app-bundle-id (
<包标识符>
):- 为 macOS 应用指定应用包标识符(通常是反向域名格式,如
com.company.app
)。 - 例:
--app-bundle-id=com.example.myapp
- 为 macOS 应用指定应用包标识符(通常是反向域名格式,如
-
–app-version (
<版本号>
):- 指定应用的版本号(通常在
package.json
中会有版本号定义)。 - 例:
--app-version=1.0.0
- 指定应用的版本号(通常在
-
–build-version (
<版本号>
):- 指定应用的构建版本号,通常在发布更新时使用。
- 例:
--build-version=100
示例
假设你要打包一个 Electron 应用,以下是常见的几个命令示例:
1. 打包为 Windows 64 位应用
electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --overwrite
2. 打包为 macOS 应用,并指定图标
electron-packager . my-app --platform=darwin --arch=x64 --out=release-build --icon=assets/icon.icns
3. 使用 ASAR 压缩并去除开发依赖
electron-packager . my-app --platform=linux --arch=x64 --out=release-build --asar --prune
4. 打包时忽略 node_modules
目录
electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --ignore="node_modules/*"
5. 打包并指定应用的版本号
electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --app-version=1.0.0
6. 一键打包各平台脚本
为了方便一键打包到各个桌面平台,写了个打包脚本
可以编写一个简单的 Node.js 脚本,使用 electron-packager
或 electron-builder
来实现一键打包不同平台的 Electron 应用。下面的示例将展示如何创建一个一键打包脚本,同时支持打包 Windows、macOS 和 Linux 平台。
1. 安装所需依赖
首先,你需要安装 electron-packager
或 electron-builder
。以下以 electron-builder
为例,因为它更为强大,支持多平台的打包。
npm install --save-dev electron-builder
2. 编写一键打包脚本
接下来,你可以创建一个 build.js
脚本来自动化打包过程,支持打包为 Windows、macOS 和 Linux 平台。
const {
exec } = require('child_process');
const path = require('path');
// 配置平台和架构
const platforms = ['win', 'mac', 'linux']; // 你可以选择需要打包的目标平台
const archs = ['x64', 'ia32']; // 你可以选择需要打包的架构
// 默认配置
const appName = 'my-app'; // 你的应用名称
// 不同平台的图标路径
const icons = {
win: path.join(__dirname, 'icon.ico'), // Windows 图标
mac: path.join(__dirname, 'icon.icns'), // macOS 图标
linux: path.join(__dirname, 'icon.png') // Linux 图标
};
// 打包命令模板
const buildCommand = (platform, arch) => {
const iconPath = icons[platform]; // 根据平台获取对应的图标路径
return `npx electron-builder --platform=${
platform} --arch=${
arch} --out=release-build --icon=${
iconPath} --appId=com.example.${
appName}`;
};
// 打包函数
function buildApp() {
platforms.forEach(platform => {
archs.forEach(arch => {
const command = buildCommand(platform, arch);
console.log(`开始打包平台: ${
platform}, 架构: ${
arch}`);
// 执行命令
exec(command, (err, stdout, stderr) => {
if (err) {
console.error(`打包失败: ${
stderr}`);
return;
}
console.log(`打包完成: ${
stdout}`);
});
});
});
}
// 执行打包
buildApp();
3. 说明
platforms
:指定需要打包的平台,这里是win
,mac
, 和linux
,你可以根据需要添加或删除平台。archs
:指定需要打包的架构,x64
和ia32
是常用的架构。你可以选择不同的架构来打包。buildCommand
:这是一个函数,生成每个平台和架构的打包命令。我们通过electron-builder
来打包应用,并使用--platform
和--arch
参数指定目标平台和架构。exec
:用于执行命令行命令。
4. 运行脚本
创建完 build.js
后,你可以通过以下命令执行打包:
node build.js
该命令将会在终端中执行,并依次为每个平台和架构执行打包操作。
5. 配置 package.json
确保你的 package.json
配置正确,尤其是 build
配置项。以下是一个基本的配置示例:
{
"name": "my-app",
"version": "1.0.0",
"description": "A sample Electron app",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "node build.js"
},
"devDependencies": {
"electron": "^23.1.0",
"electron-builder": "^25.1.8"
},
"build": {
"appId": "com.example.myapp",
"mac": {
"icon": "icon.icns"
},
"win": {
"icon": "icon.ico"
},
"linux": {
"icon": "icon.png"
}
}
}
electron-builder
提供了很多打包选项,可以在 package.json
中的 build
配置中进一步自定义。例如:
- 自定义应用图标
- 设置应用的签名和证书(对于 macOS)
- 配置自动更新(auto update)
- 设置应用程序的
dmg
、nsis
或其他安装器
更多配置可以参考 electron-builder 文档,根据需要调整。
electron-builder
打包应用后,会将应用输出到 release-build
文件夹中。你可以根据需要更改输出目录。
最终打包的成品长这样