什么是electron
说起跨平台桌面应用 可能第一反应是QT 由于比较底层,其性能极高 但是由于用C++ 开发 对于前端来说成本比较大
然后就是NW前几年还是很活跃的 毕竟 钉钉 微信web开发工具都是基于它开发的,但是其所有窗口共享一个node.js环境所以耦合行比较高,后面基本半死不活了。
而electron就是一款相比于QT更容易上手,比NW更加全面,社区更加活跃的一款一个跨平台的、基于 Web 前端技术的桌面 GUI 应用程序开发框架。下面看看3者的对比图:
正如官方文档所说:Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js , Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需要本地开发 经验。 www.electronjs.org/
安装并运行:
1.首先安装electron,和正常安装依赖包一样就行,由于文件相对较大,所以最好使用淘宝镜像或者yarn;
2.然后要在最外层目录创建main.js作为程序的主进程;
3.然后添加package.json中的 "main": "main.js";
4.最后为应用添加启动命令 "electron-start": "electron ." 正常情况下先启动项目,在运行启动命令就可以了。但是为了方便可以设置一条命令达到目的: 由于我是用的umi构建项目所以直接监听8000端口
"electron-dev": "concurrently \" wait-on http://localhost:8000 && electron .\" \"npm start\" ",
知道了启动的命令后,我得在main.js中写入主进程相关的逻辑:
主进程可以做些什么
ps:只列举一部分
监听electron初始化 设置主窗口参数 BrowserWindow
1.创建浏览器窗口
const { app, BrowserWindow} = require('electron');
function createWindow() {
//创建浏览器窗口,宽高自定义具体大小你开心就好
mainWindow = new BrowserWindow({
width: 1150,
height: 750,
minWidth: 1150,
minHeight: 750,
frame: true,
resizable: false,//禁止改变主窗口尺寸
thickFrame: true,
webPreferences: {
javascript: true,
plugins: true,
nodeIntegration: true, // 不集成 Nodejs
webSecurity: false,
enableRemoteModule: true,//使用Remote
contextIsolation:false//隔离上下文
}
})
const ipc = require('electron').ipcMain;
ipc.on('close', function () { //'close 是自定义的命令 ,只要与页面发过来的命令名字统一就可以
//接收到消息后的执行程序
// mainWindow.destroy()
// app.quit();
// app.quit()
// mainWindow.hide()
})
mainWindow.webContents.openDevTools()
if (isDevelopment) {
// 加载应用
// 打开开发者工具,默认不打开
mainWindow.loadURL('http://localhost:8000/')
} else {
//正式版本
const pathname = path.join(__dirname, 'dist/index.html')
mainWindow.loadFile(pathname)
}
// 关闭window时触发下列事件.
mainWindow.on('closed', (e) => {
//回收BrowserWindow对象
mainWindow = null;
})
}
2.当electron初始化完毕,调用函数创建窗口
app.whenReady().then(createWindow)
//or
app.on('ready', createWindow)
自定义托盘
const { Tray,Menu } = require('electron');
let trayMenuTemplate = [
{
label: 'BIM族库',
click: function () {
mainWindow.show();
}
},
{
label: '退出',
click: function () {
app.quit();
app.quit();//因为程序设定关闭为最小化,所以调用两次关闭,防止最大化时一次不能关闭的情况
}
}
];
//系统托盘图标目录
let trayIcon = path.join(__dirname, '');//app是选取的目录
appTray = new Tray(path.join(trayIcon, 'icon.ico'));//app.ico是app目录下的ico文件
//图标的上下文菜单
const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
//设置此托盘图标的悬停提示内容
appTray.setToolTip('标题');
appTray.setContextMenu(contextMenu);
//单击右下角小图标显示应用
appTray.on('click',function(){
mainWindow.show();
})
自定义弹窗 由于是窗口 所以浏览器的原生弹窗要捕获也可以自定义
const { dialog } = require('electron');
function showMessage(text) {
const options = {
type: 'info',
title: '提示',
message: text,
}
dialog.showMessageBox(options)
};
与渲染进程通信
1.渲染进程发送消息给主进程
可以通过ipcRenderer.send发送自定义指令消息
import { ipcRenderer } from 'electron';
ipcRenderer.send('aaa'); //aaa是自定义指令
2.主进程监听渲染进程send的消息
可以通过ipc.on监听渲染进程发送的具体指令
然后可以通过mainWindow.webContents.send或者e.reply回消息给渲染进程 有点类似聊天
const ipc = require('electron').ipcMain;
ipc.on('big', (e)=>{
mainWindow.maximize() //最大化窗口
mainWindow.webContents.s
end或者('tobig')
//e.reply回消息给渲染进程('tobig',true)
})
3.渲染进程接收
和主进程类似不过主进程是ipcMain 渲染进程是ipcRenderer
import { ipcRenderer } from 'electron'
ipcRenderer.on('aaa',()=>{
})
4.或者直接在渲染进程使用remote,它可以调用主进程对象的方法
import { remote } from 'electron';
const BrowserWindow = remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://www.baidu.com');
但是这里要提一点的是 es6的引入electron是会报错的 # fs.existsSync is not a function
我目前有2种比较靠谱的解决方式:
1.可以在index.html 全局引入 创建一个js文件全局引入把对象挂载在window上
renderer.js: global.electron = require('electron');
index.html:
<script>
window.electron = require('electron');
</script>
2.webpack配置文件中加入 target('electron-renderer')
第1种方案遇到umi就难受了还要在src下创建document.ejs来引入
所以最好交给webpack来做
chainWebpack (config,{webpack}) {
config
.target('electron-renderer')
},
打包
electron-packager 和 electron-builder
1.注意点
不是history模式 如果使用了打包后就会找不到css和js文件 访问路径不对
项目路径不能有中文 巨坑
electron-builder一定要安在devDependencies下
网络不好会很难 因为要重新下载electron 配置.npmrc文件
使用electron-packager注意文件权限和需要忽略的文件
2.使用electron-packager
缺点: 不支持更新安装 可配置项比较少
优点: 由于不做复杂的操作 配置项也是基础的 所以打包速度快
"packager-build": "electron-packager . app --out BIMapp --arch=x64 --icon ./public/bim.ico --overwrite --ignore=node_modules"
//
app是应用的名称
--out 打包完的可执行文件,放在在哪里
--arch操作系统
-- icon应用图标
--overwrite是否覆盖原有文件
ignore需要忽略的文件
.exe就是打包好的应用程序 项目代码全都放在reources中
3.使用electron-builder
打包前要先打包项目代码
"builder": "cross-env npm run build && cross-env node electron-build/index.js",
electron-build/index.js:
const defaultConfig = {
ia32: true,
config: {
'appId': appId,
'productName': productName, //项目名 这也是生成的exe文件的前缀名
'copyright': 'lzg',//版权信息
'asar': false, //是否需要签证
'compression':normal' ,// 压缩级别 store | normal | maximum
'extraMetadata': { // 打包时覆盖package.json
'name': name // 默认安装目录
},
'directories': {//输出文件夹 带上版本信息
'output': `app/music.test}/v${_package.version}`
},
'publish': {
'provider': '', // 服务器提供商,也可以是GitHub
'url': ''// 服务器地址
},
'files': [
'main.js',
'main/**/*',
'from': 'dist/index',
'to': 'dist',
'filter': ['**/*', '!*.map']
],
'dmg': { //ios系统
'sign': false,//签名
'icon':'', //图标
// 'background': 'electron-build/resource/background.jpg' // 背景图
},
...macSignConfig,
'mac': {
'identity': '', //身份信息
'hardenedRuntime': true,
'gatekeeperAssess': false,
'entitlements': 'electron-build/entitlements.mac.plist',
'entitlementsInherit': 'electron-build/entitlements.mac.plist',
'target': [
// 'dir'
'dmg',
'zip'
],
'icon': '', //图标
'category': 'io.bell.Education',
'extendInfo': {
'CFBundleURLTypes': 'codesprite',
'NSMicrophoneUsageDescription': 'music需要您的麦克风权限',
'NSCameraUsageDescription': 'music需要您的视像头权限'
}
},
'win': { //win系统
'artifactName': '姓名_v${version}.${ext}',//名称
'icon': '', //图标
'target': [
{
'target': 'nsis',
'arch': [
'x64'
]
}
]
// ...winSignConfig
},
'nsis': {//nsis相关配置,打包方式为nsis时生效
'language': '0x0804',
'oneClick': false,// 是否一键安装
'allowToChangeInstallationDirectory': true,// 允许修改安装目录
'allowElevation': true,// 允许请求提升,如果为false,则用户必须使用提升的权限重新启动安装程序。
'createDesktopShortcut': true,// 创建桌面图标
'createStartMenuShortcut': true,// 创建开始菜单图标
'installerIcon': '',// 安装图标
'deleteAppDataOnUninstall': true//卸载清理用户数据的。
}
}
}
builder
.build(defaultConfig)
.then(results => {
})
.catch((err) => {
console.log(err)
})
以上是我的常用打包配置信息 一些主要的说明都已经标注
到此:你已经完成了一款electron项目的打包