背景
近期公司几个大神应公司需求自研+自制了一个硬件(街机上的电子投币开关),用的树莓派,里面需要一个自启动的应用程序,展示一个付费的二维码和一些维护或者等待页面之类的,公司没有专职开发桌面应用的,机会当然就给了前端...,还好有electron,下面简单记录一下这个项目开发时候需要安装哪些工具与步骤。
创建项目
安装脚手架vue cli
npm install -g @vue/cli
创建项目
vue create vue-electron
添加electron插件
vue add electron-builder
这里可能会非常慢,最终导致超时失败。这是因为需要根据系统来下载electron的基础库,由于网络原因,建议此处使用设置npm proxy来进行下载。不建议使用其他镜像源下载,可能会导致最终打包失败。
启动
此时项目src文件夹下就多了一个background.js,这里就是electron主进程相关代码,负责和我们的vue页面(渲染进程)进行交互。
执行以下代码启动项目
npm run electron:serve
配置background.js
//background.js
//文件头部,引用增加ipcMain用于通信
import { app, protocol, BrowserWindow, ipcMain } from 'electron'
import { createProtocol } from '@matthijsburgh/vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
//窗口启动增加选项
const win = new BrowserWindow({
width: 800, //窗口默认宽度
height: 600, //窗口默认高度
useContentSize: false,
frame: true, //取消window自带的关闭最小化等
resizable: false, //禁止改变主窗口尺寸
transparent: false, //透明
hasShadow: true, //窗口阴影
maximizable: true, //是否允许最大化
webPreferences: {
enableRemoteModule:true, //在渲染进程启用remote模块
nodeIntegration: true, //在渲染进程启用Node.js
contextIsolation:false,
webSecurity: false,
backgroundThrottling: false, //程序在最小化时渲染进程不冻结
}
})
//由于渲染进程中electron.remote已废弃,需要手动引入,并在每一个browserwindow中启用remote
require('@electron/remote/main').initialize()
require("@electron/remote/main").enable(win.webContents);
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await 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')
}
配置main.js
//main.js
const electron = window.require('electron') //引用electron
const fs = window.require('fs') //引用Node模块fs
const remote = window.require('@electron/remote') //引用remote模块用于通信、打开文件弹框等
Vue.prototype.$electron = electron
Vue.prototype.$fs = fs
Vue.prototype.$remote = remote
页面应用
//在页面中使用相关API
this.$electron.ipcRenderer.sendSync('testMsg',data); //与主进程通信
this.$remote.getCurrentWindow().minimize(); //最小化窗口
this.$fs.existsSync("C:/test.js"); //调用nodejs方法查找文件是否存在
打包配置vue.config.js
module.exports = {
pluginOptions: {
electronBuilder: {
"customFileProtocol": "./", //增加此项让css中相对引用的文件能正常访问,否则一些css库中的字体会无法显示
"builderOptions": {
"extraResources": [
"./extraResources/**", //这里指定外部资源文件夹,你可以把一些外部程序放在./extraResources中,比如ffmpeg等,打包时electron将直接原样拷贝
"./node_modules/@electron/remote/**",//必须添加这一行否则remote会引用不到
],
"productName": "",
"appId": "",
"copyright":"",// 版权信息
"directories": {
"output": "./build" //输出文件夹
},
"afterSign": "", //签名文件
"dmg": { //输出mac的dmg时图标位置
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"mac": {
"icon": "./applogo.icns",//mac图标,必须至少包含512*512尺寸的图标
"target":[{
"target": "dmg", //设置输出dmg安装包
"arch": ["arm64", "x64"], //arm64是apple silicon机器专用的包;x64是intel版的包,两种电脑都能用,不过x64运行启动会慢一点;这里你可以填universal,这样会生成一个arm64+x64打出来然后装一起的一个包(体积也是两种应用之和),运行时会自动选择版本
}],
"identity": "your name",
"entitlements": "./entitlements.mac.plist", //签名必须
"entitlementsInherit": "./entitlements.mac.inherit.plist",//签名必须
"entitlementsLoginHelper": "./entitlements.mas.loginhelper.plist",//如果需要mac的mas版打包,则需要此项
},
"win": {
"icon": "./applogo.ico",//win打包图标
"target": [{
"target": "nsis",// 利用 nsis 制作安装程序
"arch": [
"x64",//64 位
]
}]
},
"nsis": {
"oneClick": false, // 是否一键安装
"allowElevation": true, // 允许请求提升. 如果为 false, 则用户必须使用提升的权限重新启动安装程序.
"allowToChangeInstallationDirectory": true, // 允许修改安装目录
"installerIcon": "./applogo.ico",// 安装图标
"uninstallerIcon": "./applogo.ico",// 卸载图标
"installerHeaderIcon": "./applogo.ico", // 安装时头部图标
"createDesktopShortcut": true, // 创建桌面图标
"createStartMenuShortcut": true,// 创建开始菜单图标
"shortcutName": "DNG自动转换工具", // 图标名称
"perMachine": true
},
}
}
},
configureWebpack: config => {
return {}//webpack相关配置
}
}
打包APP
npm run electron:build
打包后运行偶尔出现闪退问题
解决方案
//background.js
import { app } from 'electron'
app.commandLine.appendSwitch('--no-sandbox'); //该行应在app.on('ready')前面执行
require报错
require无法引用,根本原因node中的require覆盖了webpack的require,这就导致了打包失败
- 解决方案一
-
//background.js //在渲染进程中禁用Node.js。在主进程background.js中,将nodeIntegration选项设置为false //这样就可以正常使用require了。副作用是无法访问一些底层的参数比如__dirname,当引用的组件使用这些参数时会报错。 const win = new BrowserWindow( webPreferences: { nodeIntegration: false //该选项在渲染进程中禁用Node.js } })
-
- 解决方案二 (推荐)
-
//background.js const win = new BrowserWindow( webPreferences: { nodeIntegration: true //该选项在渲染进程中启用Node.js } })
-
//main.js //在require组件时,必须在main.js中引用,并且必须使用window.require const electron = window.require('electron') Vue.prototype.$electron = electron
这样就可以在页面中通过this.$electron访问到electron的API了
-
以上就是这次大概的开发流程,记录以下以后可以备用,毕竟开发开发桌面应用的实战机会不多
- THE END -
最后修改:2024年10月24日
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/index.php/2020/02/14/electron-vue/