# 1. 进程

  • chromeelectron一样,有一个主进程和多个渲染进程
  • 每个渲染进程对应一个窗口
  • 渲染进程能够调用 DOMAPInodeAPI
  • 主进程能调用 nodeAPI

# 1.1. 主进程特点

  • 支持nodejs
  • 只有一个,作为整个程序的入口点;
  • 创建渲染进程;
  • 可以使用和系统对接的Eelectron API,比如上传文件、创建菜单等。

# 2. IPC进程间通信

ipcRenderer.send('msg', 'hello')

ipcMain.on('msg', (event, arg) => {
  ipcMain.reply('reply', 'hi')
})

ipcMain.emit(‘msg’,’hi’)

# 3. 启动命令

  • 使用concurrently同时运行reactelectronconcurrently \"electron .\" \"npm start\"
  • 使用wait-on插件,等待localhost:3000加载完之后,再运行electron
  • 安装cross-env,不在浏览器中打开localhost:3000BROWSER=none

最后的命令为:

 "dev": "concurrently \"wait-on http://localhost:3000 && electron .\"  \"cross-env BROWSER=none npm start\""

# 3.1. nodemon监控某些文件变动,自动刷新

"onlyEle": "nodemon --watch main.js --watch ./src/utils/menuTemplate.js --exec \"electron .\" "

注意加上转义符号\

# 4. API相关

# 4.1. parent 属性

从窗口增加 parent 属性,作用是当父窗口关闭时,子窗口也跟着关闭。

# 4.2. nodeIntegration

electron 项目中,HTML 页面里面引用 nodejs 的模块时缺报了错,提示 require 未找到,原来是electron 升级到5.0之后默认关闭了 html 页面启用 nodejs 环境的问题!

webPreferences:{
  nodeIntegration:true
}

# 4.3. loadUrl

electronloadUrl 当作 loadFile 使用,需要加上file://协议符号

# 4.4. 上下文菜单 Menu、MenuItem

menu = new Menu()

menu.append(new MenuItem({
  label: 'Print',
  accelerator: 'CmdOrCtrl+P',
  click: () => { console.log('time to print stuff') }
}))

# 4.5. 打开导入文件对话框

remote.dialog.showOpenDialog({
  title: '',
  properties: [],
  filters: []
})

返回对象,包括 canceledfilepaths

# 4.6. 打开成功提示信息

remote.dialog.showMessageBox({
  type: 'info',
  title: ``,
  message: ``,
})

# 4.7. electron 打开控制台

mainWindow.webContents.openDevTools()

# 4.8. 上下文菜单

electron上下文菜单(右键菜单),需要先判断点击目标是否是文件item的子元素,然后响应contextmenu事件:

const menu =  new Menu()

menu.append(new MenuItem(item))
menu.popup({ window: remote.getCurrentWindow() })

# 4.9. 设置原生菜单

const menu = Menu.buildFromTemplate(menuTemplate)

Menu.setApplicationMenu(menu)

在主进程中,还可以动态设置某些菜单是否禁用:

menu.items[0].submenu.items[0].enabled = false

# 4.10. electron 的 shell

可以用默认浏览器打开网页,可以打开文件夹

# 5. 相关插件

# 5.1. electron-store进行持久化数据

数据持久化,就是防止刷新就没了,比如数据库、localStorage、本地文件等

# 5.2. electron-is-dev插件

electron-is-dev插件判断是开发环境还是线上

const isDev = require('electron-is-dev')

# 5.3. 安装devtron后,能查看IPC通信信息

代码:

require('devtron').install()

# 6. 相关问题

# 6.1. 用window.require替代require

electron + react中无法使用require的原因是被webpack劫持了,在node_modules中去找了。

加上window.require后,可以把控制权交给node.js

# 6.2. HTTPS 证书不合法时 ,electron 会自动退出

app.on('certificate-error'(e, cb)=>{ 
  e.preventDefault(); 
  cb(true) 
})

# 6.3. 提示跨域

渲染进程发送http请求,是从file协议上发的,提示跨域,需要设置:

webPreferences:{ 
  webSecurity: false 
}

# 6.4. electron-builder打包时下载依赖失败,解决方法

  1. 在淘宝镜像上下载相应的包,https://npm.taobao.org/mirrors/electron/。按照包名下载
  2. 放到相应系统的缓存目录下。
macOS:/Library/Cache/electron-builder
windows: %LOCALAPPDATA\electron-builder\cache

# 6.5. 解决 Windows 下安装electron 8.0.0node install.js卡住的问题

  1. 卡在 node install.jsctrl+c 退出进程
  2. cd node_modules/electron && code install.js (打开install.js
  3. 修改代码如下:
mirrorOptions:{
  mirror:'https://npm.taobao.org/mirrors/electron/',
  customDir:'8.0.0',
  // customFilename:'electron-8.0.0-win32-x64.zip'
}

这个方案在其他文章中也有所提及,只是版本不同,修改的参数不同了

# 7. 打包

# 7.1. 打包中的坑

  1. electron-builder中把react build后的文件夹当成静态文件,不给打包,所以在配置的**files**字段中手动写入要打包的文件。 (提示错误为找不到build/index.html) 1.1 glob pattern, 比如build/**/*,两个星号匹配所有子文件夹的文件,一个星号匹配当前文件夹下的所有文件。**/*就是当前目录下的所有文件。 1.2 只要一设置files字段,默认配置就不生效了,所以必须全部写进去,包括main.js以及它依赖的文件和包。
  2. 修改extends属性为null,禁掉自动修改打包入口文件(应始终是main.js)(提示错误为找不到入口文件build/electron.js)。
  3. package.json中添加homepage'./',改为相对路径(提示错误为静态文件路径不对,/static/css/static/js等)。
  4. 把所有在main.js中引用的插件,放到dependencies中去,否则会报错。

# 7.2. 打包体积优化

  1. electron打包时要把需要的包名称写到package.jasondependencies中,electron-builder不会打包devDependencies中的包。 所以一个优化的点就是将main.js中不需要的包移动到devDependencies中去。因为react已经将其他的打包过了,且是压缩的形式。打包后的node_modules文件夹就会变得很小。

  2. webpackmain.js及其依赖打包,就可以在配置的files中少写文件。同时要在配置中添加extraMetadata字段,以覆盖开发中的入口文件main.js

"extraMetadata": {
  "main": "./build/main.js"
},

并且将prepackpredist改为npm run build && npm run buildMain,以及在main.js中把loadUrl路径更新。同时把dependencies更新,把main.js中使用的去掉。

# 7.3. electron-builder --direlectron-builder的不同

  • "electron-builder --dir", 打包生成安装完毕后的文件
  • "electron-builder",生成dmgexe等源文件

# 8. 自动更新

  1. 自动发布release

添加publish配置:[‘github’];增加命令release,和dist指令相同,不过它会自动发布一个release;同时增加指令prerelease,和predist相同。

如果更新到github需要token,所以完整命令为:

“release”: "cross-env GH_TOKEN=123 electron-builder"
  1. 添加自动更新功能

安装electron-updater,比electron内置的更新配置简单。

# 9. 在main.js中使用ipcMain监听事件,为什么有的地方可以用event.sender去发送信息,有的地方却只能用mainWindow来发送呢?

  • mainWindow指定发送,而event.sender进程内回调发送。
  • 就是一个页面内发信息发送到main.js,然后用event.sender进行进程内在发送回去。
  • mainwindow实际上是新建的一个进程窗口,我们就指定给他发送了。

# 10. Electron 镜像地址

https://npm.taobao.org/mirrors/electron/