electron(WebRTC远程控制)代码架构(3)

1,291 阅读2分钟

项目目录

  1. 通信方面
    1. app/main 下有 ipc.js 和 signal.js
      1. ipc 负责主进程和渲染进程的通信
      2. signal 负责客户端与 server的 ws 服务的通信
        1. client 与 server 建立 ws 服务,每次 ws.on('message')时,signal.emit 把信息发射出去(singal 是一个 EventEmitter 实例)
        2. 在 ipc 中 ,把 signal.on(对应的事件) 再去给渲染进程通知(通过主进程 win.webContents.send(channel, ...args))
├── app  // 主入口
│   ├── main
│   │   ├── crash-reporter.js
│   │   ├── index.js
│   │   ├── ipc.js  // ipc通信
│   │   ├── robot.js
│   │   ├── signal.js // 信令通信
│   │   ├── trayAndMenu  // 托盘
│   │   │   ├── darwin.js
│   │   │   ├── icon_darwin.png
│   │   │   ├── icon_darwin@2x.png
│   │   │   ├── icon_win32.png
│   │   │   ├── icon_win32@2x.png
│   │   │   ├── index.js
│   │   │   └── win32.js
│   │   ├── updater.js
│   │   └── windows  // 窗口
│   │       ├── about.js  // 关于窗口
│   │       ├── control.js // 控制窗口
│   │       ├── icon.png
│   │       └── main.js  // 傀儡窗口
│   └── renderer   // view
│       ├── pages
│       │   ├── control   // 控制端 view
│       │   │   ├── app.js
│       │   │   ├── index.html
│       │   │   └── peer-control.js  // 控制端主逻辑
│       │   └── main  // 打包后的产物,忽略!
│       │       ├── asset-manifest.json
│       │       ├── favicon.ico
│       │       ├── index.html
│       │       ├── logo192.png
│       │       ├── logo512.png
│       │       ├── manifest.json
│       │       ├── robots.txt
│       │       └── static
│       └── src   // 傀儡端代码,用的cra
│           └── main
│               ├── README.md
│               ├── build.js
│               ├── config-overrides.js
│               ├── package-lock.json
│               ├── package.json
│               ├── pnpm-lock.yaml
│               ├── public
│               └── src  // 傀儡端主逻辑
├── build  // 打包后的
│   └── config.gypi
├── package.json
├── pnpm-lock.yaml
├── resources   // 打包需要的资源
│   ├── background.png
│   ├── background@2x.png
│   ├── icon.icns
│   ├── icon.ico
│   └── icon.png
└── robot_test.js

进程间通信

  1. 单向 ipcMain.on , ipcRenderer.send
  2. 双向 ipcMain.handle , ipcRenderer.invoke , 渲染进程执行 invoke 可以拿到主进程执行的结果的回调,在执行逻辑
  3. 主进程通过 mainWindow.webContents.send 向对应的渲染进程发信息;ipcRenderer.on
  4. 主进程,与主进程通信。因为 ipcMain是一个 Emitter 的实例,可以直接使用 ipcMain.emit 和 ipcMain.on 通信

注意,electron 的上下文是隔离的,也就是 预加载脚本和Electron的内部逻辑运行,和所加载的 webContent网页 之间,是独立的上下文;所以在 Renderer 进程中,不能直接使用 ipcRenderer.on 一个事件

  • 解决办法2个:
  • 第一个方法:是在 creatWindow 的时候,修改属性
 webPreferences:{
        nodeIntegration:true,
        contextIsolation:false // 上下文隔离环境取消,默认是true,为了安全
    }
  • 第二个方法:在 preLoader.js 中,显式的暴露出要调用的 api,在 renderer在中使用

// main.js
const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
})


// preload.js 
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
    setTitle: (title) => ipcRenderer.send('set-title', title)
})


// renderer.js 
const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
    const title = titleInput.value
    window.electronAPI.setTitle(title)
});

IPC回顾

  1. 渲染进程请求 + 主进程响应 (获取自己的控制码) ipcRenderer.invoke + ipcMain.handle
  2. 主进程推送(告知状态),webContents.send + ipcRenderer.on
  3. 渲染进程发起请求 (申请控制), ipcRenderer.send + ipcMain.on

其他

react 项目中支持 electron 模块

方法一 使用 window.require 加载
  • 在 doc 项目中有叙述,略过
方法二 cra 项目,修改webpack配置,支持识别 electron 环境的依赖
  1. 如 在renderer 页面中直接使用
import { ipcRenderer }  from 'electron'
  1. 安装
    1. "customize-cra": "^1.0.0",
    2. "react-app-rewired": "^2.2.1"
  2. 新增覆盖文件
  3. config-overrides.js

const { override  } = require('customize-cra');

function addRendererTarget(config) {
    config.target = 'electron-renderer'
    return config
}

module.exports = override(addRendererTarget)

  1. 修改脚本,用 react-app-rewired 启动
"scripts": {
   "start": "BROWSER=none react-app-rewired start",
},