# hx-electron
**Repository Path**: code_yu/hx-electron
## Basic Information
- **Project Name**: hx-electron
- **Description**: 快速搭建 electron ,vue环境,实现自动更新,集成了sqlite数据库
- **Primary Language**: JavaScript
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 19
- **Forks**: 3
- **Created**: 2020-09-20
- **Last Updated**: 2025-09-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
@[TOC](electron 打包,自动更新,修改默认安装目录)
# 使用
## 克隆项目
```
git clone https://gitee.com/code_yu/hx-electron.git
cd hx-electron
```
## 安装依赖
```
yarn install
```
### 开发环境启动
```
yarn electron:serve
```
### 正式打包
```
yarn electron:build
```
### 安装问题
sqlite3、electron 安装失败,一般是国内网络问题,用梯子安装依赖一般都没有问题。
# 技术栈 文档
- [Electron](https://www.electronjs.org/docs/all)
- [Vue3](https://v3.cn.vuejs.org/) JavaScript 框架
- [element-plus UI](https://element-plus.gitee.io/zh-CN/component/button.html) 优秀的前端UI组件
- [vue-config-js](https://cli.vuejs.org/zh/config/#vue-config-js) vue.config.js 配置
- [vue-cli-plugin-electron-builder](https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/guide.html#table-of-contents) 打包工具
- [nsis](https://www.electron.build/configuration/nsis) 打包配置
- [electron-updater](https://www.electron.build/auto-update) 应用自动更新
- [electron-log](https://github.com/megahertz/electron-log)
> 如需查看打包后应用的日志,那么需从命令行启动应用
``` shell
$ cd demo_path
$ ./demo.exe
````
# 应用自动更新
### 1. 配置 `vue.config.js` 中的应用更新服务器地址
详细打包配置请看 [vue.config.js 完整示例](#other-1)
``` javascript
module.exports = {
pluginOptions: {
electronBuilder: {
...
publish: [
{
provider: 'generic',
url: 'http://127.0.0.1/app/'
}
]
...
}
}
}
}
```
### 2. 在主进程写更新应用逻辑
在 `background.js` 文件或 `main.js` 中写入更新逻辑
以下为 `background.js` 完整示例:
``` javascript
'use strict'
import { app, protocol, BrowserWindow, Menu, dialog } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const { autoUpdater } = require('electron-updater')
const path = require('path')
const log = require('electron-log')
const isDevelopment = process.env.NODE_ENV !== 'production'
let win
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
log.info('启用日志')
function createWindow () {
Menu.setApplicationMenu(null)
// Create the browser window.
win = new BrowserWindow({
width: 1400,
height: 800,
webPreferences: {
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
preload: path.join(__dirname, 'preload.js')
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
autoUpdater.checkForUpdates()
}
win.on('closed', () => {
win = null
})
}
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
// ======================================================================
// 更新模块
// ======================================================================
if (!process.env.WEBPACK_DEV_SERVER_URL) {
autoUpdater.autoDownload = false
autoUpdater.signals.updateDownloaded(() => {})
autoUpdater.on('error', (error) => {
log.warn('检查更新失败: ' + error == null ? 'unknown' : (error.stack || error).toString())
// dialog.showErrorBox('Error: ', error == null ? 'unknown' : (error.stack || error).toString())
})
autoUpdater.on('update-available', (info) => {
// var appInfo = {
// info: info.version,
// files: info.files,
// path: info.path,
// sha512: info.sha512,
// releaseDate: info.releaseDate
// }
dialog.showMessageBox({
type: 'info',
title: '更新提示',
message: '软件需要更新,您是否立即更新?',
buttons: ['推迟', '立即更新']
}).then((res) => {
log.warn('index:' + res.response)
if (res.response === 1) {
log.warn('选择升级')
autoUpdater.downloadUpdate()
} else {
log.warn('选择不升级:')
}
})
})
// 检查更新时触发
autoUpdater.on('update-available', (res) => {
log.warn('检查更新时触发')
// log.warn(res)
// dialog.showMessageBox({
// title: '检查更新',
// message: '正在检查更新'
// })
})
// 没有可用更新
autoUpdater.on('update-not-available', () => {
log.warn('没有可用更新')
// dialog.showMessageBox({
// title: '已是最新版',
// message: '当前版本是最新版本。'
// })
})
// 安装更新
autoUpdater.on('update-downloaded', (res) => {
// log.warn(res)
log.warn('下载完毕!提示安装更新')
dialog.showMessageBox({
title: '升级提示!',
message: '已自动升级为最新版,请重启应用!'
}, () => {
log.warn('确认安装')
setImmediate(() => autoUpdater.quitAndInstall(true, true))
})
})
// 下载进度
// autoUpdater.on('download-progress', (event) => {
// log.warn(event.percent)
// })
}
```
### 3. 打包一个应用(v1.0.0)
打包后 `dist_electron` 目录中有 `*.blockmap` 格式的文件;
将文件复制到 '更新服务器' (http://127.0.0.1/app/) 目录下;
### 4. 打包一个升级版的应用(v1.1.0)
打包后 `dist_electron` 有如下三个文件:
- `新版本安装包.exe`
- `新版本_v1.1.0.blockmap`,
- `latest.yml`
将上面三个文件复制到 ‘更新服务器’ (http://127.0.0.1/app/) 目录下;
以后每次有更新就复制这三个文件至 ‘更新服务器’,保留旧版本的 `*.blockmap` 文件,旧版本的应用的执行文件(`.exe`)可以删除。
# 其他
## 打包
### 打包配置 vue.config.js 完整示例
``` javascript
module.exports = {
pluginOptions: {
electronBuilder: {
// 预加载文件
preload: 'src/preload.js',
// 渲染进程也可以获取原生node包
nodeIntegration: true,
// 打包配置
builderOptions: {
// 发布者名称
productName: 'hx-admin',
// 包名
appId: 'cn.xxx.hxadmin',
copyright: 'hui xian copyright',
// 更新的服务器
publish: [
{
provider: 'generic',
url: 'http://127.0.0.1/app/'
}
],
asar: false,
// 不需要打包至asar中的文件如数据库文件,icons文件
extraResources: [
{
from: './data/db.db',
to: '../data/db.db',
filter: ['**/*']
}, './icons'],
win: {
// 图标文件大小为 256*256
icon: './icons/icon.ico',
target: [
{
target: 'nsis',
arch: [
// 'x64',
'ia32'
]
}
],
// 打包权限 asInvoker | highestAvailable
requestedExecutionLevel: 'highestAvailable'
},
// 安装包名称,可自行配置
artifactName: '${productName}_Setup_${version}_${platform}.${ext}',
nsis: {
// 一键安装,如果设为true,nsis设置就无意义请直接删除 nsis 配置
oneClick: false,
// true全用户安装【目录为:C:\Program Files (x86)】,false安装到当前用户
perMachine: true,
// 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
allowElevation: true,
// 允许修改安装目录
allowToChangeInstallationDirectory: true,
// 创建桌面图标
createDesktopShortcut: true,
// 创建开始菜单图标
createStartMenuShortcut: true,
// 快捷方式的名称,默认为应用程序名称
// shortcutName: 'HX',
// 安装图标
installerIcon: './icons/icon.ico',
// 卸载图标
uninstallerIcon: './icons/icon.ico',
// 安装时头部图标
installerHeaderIcon: './icons/icon.ico',
// 配置 nsn 如修改默认安装目录
include: './installer.nsh'
}
}
}
}
}
```
### 安装时修改默认目录
#### 1. 在 nsis 添加 `include` 属性:
> 详细打包配置请看 [vue.config.js 完整示例](#other-1)
``` javascript
module.exports = {
pluginOptions: {
electronBuilder: {
...
nsis: {
// 配置 nsn 如修改默认安装目录
include: './installer.nsh'
...
}
...
}
}
}
}
```
#### 2. 根目录新建 `installer.nsh` 文件,内容如下:
>`installer.nsh` 一般和`vue.config.js`为同级目录
> `D:\Program Files (x86)` 为定义安装目录,可修改
> `${PRODUCT_NAME}` 为应用名称变量,一般没不需要改
```
!macro preInit
SetRegView 64
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files\${PRODUCT_NAME}"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files\${PRODUCT_NAME}"
SetRegView 32
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files (x86)\${PRODUCT_NAME}"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files (x86)\${PRODUCT_NAME}"
!macroend
```
---
## 使用自定义的 `svg` 图标
1. 在[iconfont](https://www.iconfont.cn/)下载`.svg`图标;
2. 将下载的`.svg`文件放置 `/src/icons/svg` 目录下;
3. 执行压缩svg文件的指令 `yarn svgo` ;