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
进程间通信
实践
前提 上一帖搭建的环境
https://github.com/NightsLight-hub/vcped-test.git
tag: 0-initenv
目标
- 主进程启动httpserver,将rest的pathVariable作为查询关键词发送渲染进程, 用span展示
1. 配置preload,暴露IpcRenderer给window对象
由于Electron的上下文隔离,我们需要利用contextBridge来将IpcRender暴露到渲染进程.
在vue.config.js中新增如下内容,参考
module.exports = {
pluginOptions: {
electronBuilder: {
nodeIntegration: false,
preload: 'src/preload.js'
}
}
};
在src(background.js同级目录)中新建preload.js
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('ipcRenderer', {
send: (channel, data) => {
ipcRenderer.send(channel, data);
},
receive: (channel, func) => {
ipcRenderer.on(channel, (event, ...args) => func(event, ...args));
},
invoke: (channel, func, ...args) => {
ipcRenderer.invoke(channel, ...args).then((result) => {
func(result);
});
}
});
在background.js,主窗口的webPreferences中增加preload 配置
const browserWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: path.join(__dirname, 'preload.js') // 增加preload配置
}
});
在渲染进程中用IpcRenderer来
修改home.vue, mounted 钩子中,用ipcRenderer来获取mainMsg
的消息
<template>
<div class="home">
<span>{{ msg }}</span>
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: 'Home',
data () {
return {
msg: ''
};
},
mounted () {
// eslint-disable-next-line no-debugger
debugger;
window.ipcRenderer.receive('mainMsg', (event, ...args) => {
console.log('get mainMsg');
this.msg = args[0]; // msg 使用ipcrenderer的消息赋值
});
}
};
2. express监听20300端口,使用webcontents 发送消息到'search'通道
background.js
增加express 监听
const express = require('express');
...
async function createWindow () {
// Create the browser window.
const browserWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
});
startExpress(browserWindow);
...
}
function startExpress (browserWindow) {
const arserver = express();
arserver.get('/api/search/:word', (req, res) => {
console.log(req.params.word);
// 使用主窗口的webContents来做进程通信,发送信息
browserWindow.webContents.send('search', req.params.word);
res.send('ok');
});
}
启动调试
yarn electron:serve
使用命令行发送
curl 127.0.0.1:20300/api/msg/123
应用界面变化
本节代码可以从github获取
https://github.com/NightsLight-hub/vcped-test
tag:1-ipc