最近想要制作一个 Windows 工具箱,所以需要多集合一些功能。之前用 uniapp 制作了一些功能,为了省事,所以想要把部分 uniapp 封装成 exe 来丰富功能。
看了一下,由于 uniapp 并未提供打包 exe 的方法,所以需要借助 electron 来对编译后的内容进行打包。
最近萌生了制作一个 Windows 工具箱 的想法,希望它能整合多种实用功能,方便日常使用。由于之前用 UniApp 制作了一些工具,为了节省开发时间和重复工作量,我决定将部分 UniApp 项目封装为 EXE 文件,以丰富工具箱的功能。
UniApp 是一个强大的跨平台开发框架,支持多平台(如 H5、小程序、App)的快速开发,但目前官方并未提供直接打包成 Windows EXE 的方法。因此,我们需要借助其他工具实现这一目标。在调研过程中发现,Electron 是一个很适合的选择。
Electron 是一个用于构建跨平台桌面应用的框架,基于 Chromium 和 Node.js,允许使用 Web 技术(如 HTML、CSS 和 JavaScript)构建桌面应用。以下是它的一些优势:
接下来简单讲一下使用 Electron 将 UniApp 封装为 EXE 的具体流程:
首先,需要将 UniApp 项目构建为 H5 版本。步骤如下:
dist
文件夹,其中包含 H5 的静态文件。安装 Node.js 环境后(默认大家都安装了),按照以下步骤创建一个 Electron 项目:
准备一个正常可以打包成 web 的正常 uniapp 项目
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
环境变量:
在 PowerShell 中设置环境变量 ELECTRON_MIRROR
,指向国内镜像地址。打开 PowerShell 窗口并执行以下命令:
$env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
这个会在 PowerShell 会话中临时设置 ELECTRON_MIRROR
环境变量。
然后你可以执行以下命令来安装 Electron:
npm install --save-dev electron
这样 Electron 安装就能走国内的镜像源,而不是默认的 GitHub 源,从而减少因网络问题导致的安装失败。
打包后的内容在 unpackage/dist/build/web/
下,初始结构包括 index.html
,assets 目录以及 static 目录,需要创建你 main.js
以及 package.json
并补全相关内容即可。
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();
}
});
在 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"
}
完成 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 即可运行。
electron-builder
)进一步优化。首先时窗口大小,宽屏不太适合这个比较长的计算器,所以需要限制窗口大小为 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();
}
});
如果希望完全隐藏滚动条,可以在 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); /* 滚动条悬停颜色 */
}
在 Electron 中更换应用程序的图标非常简单。你可以通过在创建 BrowserWindow
和 app
实例时指定图标路径来设置图标。下面我将给你展示如何为 Windows 和 macOS 更换应用程序图标。
在 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
应该是你放置在项目目录中的图标文件。在 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 图标。如果你打包应用程序后,还想更换最终生成的安装包图标,你需要在打包配置中指定图标。这里以 Electron Builder 和 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
配置中,你可以在 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
.ico
格式的图标。你可以使用在线工具(如 ICO Converter)将其他格式的图像转换为 .ico
格式。.icns
格式的图标。你可以使用 macOS 自带的 iconutil
工具或者在线工具将其他格式的图像转换为 .icns
格式。.png
或 .svg
格式的图标。electron-packager
是一个常用的命令行工具,用于将 Electron 应用打包成可执行文件。它可以将你的应用程序打包为适用于不同平台(Windows、macOS 和 Linux)的安装包。
以下是 electron-packager
常用命令和参数的说明:
electron-packager <应用目录> <应用名称> --platform=<平台> --arch=<架构> --out=<输出目录>
<应用目录>
):
<应用名称>
):
<平台>
):
win32
: Windowsdarwin
: macOSlinux
: Linux--platform=win32
<架构>
):
x64
: 64 位ia32
: 32 位armv7l
: ARM(树莓派等设备)arm64
: ARM 64 位--arch=x64
<输出目录>
):
--out=release-build
--overwrite
--asar
选项可以将其压缩为单个 ASAR 文件。--asar
<图标文件>
):
.ico
、.png
等格式。常用于 Windows 和 macOS 上的应用图标。--icon=path/to/icon.ico
--prune
<路径>
):
--ignore="tests/*"
<包标识符>
):
com.company.app
)。--app-bundle-id=com.example.myapp
<版本号>
):
package.json
中会有版本号定义)。--app-version=1.0.0
<版本号>
):
--build-version=100
假设你要打包一个 Electron 应用,以下是常见的几个命令示例:
electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --overwrite
electron-packager . my-app --platform=darwin --arch=x64 --out=release-build --icon=assets/icon.icns
electron-packager . my-app --platform=linux --arch=x64 --out=release-build --asar --prune
node_modules
目录electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --ignore="node_modules/*"
electron-packager . my-app --platform=win32 --arch=x64 --out=release-build --app-version=1.0.0
为了方便一键打包到各个桌面平台,写了个打包脚本
可以编写一个简单的 Node.js 脚本,使用 electron-packager
或 electron-builder
来实现一键打包不同平台的 Electron 应用。下面的示例将展示如何创建一个一键打包脚本,同时支持打包 Windows、macOS 和 Linux 平台。
首先,你需要安装 electron-packager
或 electron-builder
。以下以 electron-builder
为例,因为它更为强大,支持多平台的打包。
npm install --save-dev electron-builder
接下来,你可以创建一个 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();
platforms
:指定需要打包的平台,这里是 win
, mac
, 和 linux
,你可以根据需要添加或删除平台。archs
:指定需要打包的架构,x64
和 ia32
是常用的架构。你可以选择不同的架构来打包。buildCommand
:这是一个函数,生成每个平台和架构的打包命令。我们通过 electron-builder
来打包应用,并使用 --platform
和 --arch
参数指定目标平台和架构。exec
:用于执行命令行命令。创建完 build.js
后,你可以通过以下命令执行打包:
node build.js
该命令将会在终端中执行,并依次为每个平台和架构执行打包操作。
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
配置中进一步自定义。例如:
dmg
、nsis
或其他安装器更多配置可以参考 electron-builder 文档,根据需要调整。
electron-builder
打包应用后,会将应用输出到 release-build
文件夹中。你可以根据需要更改输出目录。
最终打包的成品长这样