electron 进程模型
上篇帖子传送门——vue+electron 环境搭建记录(基于vue-cli-plugin-electron-builder)
electron 使用多进程架构
与chromium类似,electron使用多进程架构。单一进程架构能够节省资源,然而浏览器经常遇到恶意代码,可能导致进程崩溃,浏览器的多个页签公用一个进程必然会一损俱损,因此多进程架构更适合些(chromium多进程架构说明)。
在开发electron的过程中,我们主要接触两个进程: 主进程main process与渲染进程renderer process
主进程
每个electron 应用只有一个主进程, 对应于vcp-electron-builder搭建的项目里的background.js脚本.
主进程代码, 拥有能访问nodejs api的能力,可以require nodejs 的模块, 调用一些原生模块来与操作系统交互. 主进程负责管理electron应用的生命周期, 管理应用的窗口, 可以通过IPC模块来与渲染进程交互.
渲染进程
渲染进程就是负责渲染网页内容的, 网页html,css以及网页相关的js就跑在这里.
由于渲染进程不能用commonjs模块(至少默认不可以), 渲染进程不能用require来引入nodejs模块.(此处涉及到一些浏览器使用异步加载,因此不能用commonjs模块同步加载的原因,以后单开帖子记录)
渲染进程如果需要使用某些通过nodejs原生模块才能完成的工作(例如读取磁盘文件), 就需要用IPC来完成.
electron IPC使用
概述
官网讲的已经非常好了...
electron IPC 进程间通信
实践
前提 上一帖搭建的环境
1https://github.com/NightsLight-hub/vcped-test.git 2tag: 0-initenv
目标
- 主进程启动httpserver,将rest的pathVariable作为查询关键词发送渲染进程, 用span展示
1. 配置preload,暴露IpcRenderer给window对象
由于Electron的上下文隔离,我们需要利用contextBridge来将IpcRender暴露到渲染进程.
在vue.config.js中新增如下内容,参考
1 module.exports = { 2 pluginOptions: { 3 electronBuilder: { 4 nodeIntegration: false, 5 preload: 'src/preload.js' 6 } 7 } 8}; 9
在src(background.js同级目录)中新建preload.js
1import { contextBridge, ipcRenderer } from 'electron'; 2 3contextBridge.exposeInMainWorld('ipcRenderer', { 4 send: (channel, data) => { 5 ipcRenderer.send(channel, data); 6 }, 7 receive: (channel, func) => { 8 ipcRenderer.on(channel, (event, ...args) => func(event, ...args)); 9 }, 10 invoke: (channel, func, ...args) => { 11 ipcRenderer.invoke(channel, ...args).then((result) => { 12 func(result); 13 }); 14 } 15});
在background.js,主窗口的webPreferences中增加preload 配置
1const browserWindow = new BrowserWindow({ 2 width: 800, 3 height: 600, 4 webPreferences: { 5 6 // Use pluginOptions.nodeIntegration, leave this alone 7 // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info 8 nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, 9 contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION, 10 preload: path.join(__dirname, 'preload.js') // 增加preload配置 11 } 12 });
在渲染进程中用IpcRenderer来
修改home.vue, mounted 钩子中,用ipcRenderer来获取mainMsg的消息
1<template> 2 <div class="home"> 3 <span>{{ msg }}</span> 4 </div> 5</template> 6 7<script> 8// @ is an alias to /src 9 10export default { 11 name: 'Home', 12 data () { 13 return { 14 msg: '' 15 }; 16 }, 17 mounted () { 18 // eslint-disable-next-line no-debugger 19 debugger; 20 window.ipcRenderer.receive('mainMsg', (event, ...args) => { 21 console.log('get mainMsg'); 22 this.msg = args[0]; // msg 使用ipcrenderer的消息赋值 23 }); 24 } 25};
2. express监听20300端口,使用webcontents 发送消息到'search'通道
background.js 增加express 监听
1const express = require('express'); 2... 3async function createWindow () { 4 // Create the browser window. 5 const browserWindow = new BrowserWindow({ 6 width: 800, 7 height: 600, 8 webPreferences: { 9 10 // Use pluginOptions.nodeIntegration, leave this alone 11 // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info 12 nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, 13 contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION 14 } 15 }); 16 startExpress(browserWindow); 17 ... 18} 19 20function startExpress (browserWindow) { 21 const arserver = express(); 22 arserver.get('/api/search/:word', (req, res) => { 23 console.log(req.params.word); 24 // 使用主窗口的webContents来做进程通信,发送信息 25 browserWindow.webContents.send('search', req.params.word); 26 res.send('ok'); 27 }); 28}
启动调试
yarn electron:serve
使用命令行发送
curl 127.0.0.1:20300/api/msg/123
应用界面变化

本节代码可以从github获取
1https://github.com/NightsLight-hub/vcped-test 2tag:1-ipc