最近稍稍试了一下electron体验了一波简易开发桌面应用,将之前写的一个create-react-app改造成electron 应用,同时希望在学习electron的时候进一步加深对nodejs的了解
关于如何将一个create-react-app改造成一个electron-create-react-app
参考此文🌰
关于将electron热启加入到其中 我的例子
关于electron 目录组织的方式参考
关于electron的安全性问题
开发者能抵御这种逆向分析的手段也很有限——仅有混淆一途,而且效果也不佳,只要逆向者肯花点时间去分析,还是能够轻松逆向出源码。这也就注定了Electron只适合开源生态的程序的开发,并不适合对技术及知识产权的保护有强需求的企业和个人。
来源52破解
electron主要由两部分构成,一部分是chrome的环境,另外一部分就是集成的v8node环境。chrome环境最核心为electron提供了view的功能,就是展示网页,以及浏览器环境的api。而node提供了与电脑系统交互的环境,包括使用fs模块由或者是调用http。
关于node这里使用了一下深入nodejs的图片
再进一步看,包括解析javascript语法,以及调用libuv进行io操作等等
了解electron工作模式
在源码阅读的发现充满着大量的观察者模式的运用,需要稍微了解一下什么是观察者模式下的订阅与发布。
从窗体打开到窗体通讯原理
在electron中,整体依托的是main进程,通过执行main进程打开窗体,在执行main进程的时候,我的理解是就跟打开一个新的进程.
//main.js
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 500,
'web-preferences': {'web-security': false}
})
/*log pid*/
console.log(`Pid is ${process.pid}`)
// dev mode load the localhost and pro load the build folder file
const startUrl = process.env.ELECTRON_START_URL || url.format({
pathname: path.join(__dirname, '/../build/index.html'),
protocol: 'file:',
slashes: true
});
mainWindow.loadURL(startUrl);
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
app.on('ready', ()=>{
//main window
createWindow()
})
/*
browser-window:
https://github.com/electron/electron/blob/master/lib/browser/api/browser-window.js
*/
const {BrowserWindow} = process.atomBinding('window')
...
// Make new windows requested by links behave like "window.open"
this.webContents.on('-new-window', (event, url, frameName,
disposition, additionalFeatures,
postData) => {
const options = {
show: true,
width: 800,
height: 600
}
ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
event, url, frameName, disposition,
options, additionalFeatures, postData)
})
this.webContents.on('-web-contents-created', (event, webContents, url,
frameName) => {
v8Util.setHiddenValue(webContents, 'url-framename', {
url,
frameName
})
})
// Create a new browser window for the native implementation of
// "window.open", used in sandbox and nativeWindowOpen mode
this.webContents.on('-add-new-contents', (event, webContents, disposition,
userGesture, left, top, width,
height) => {
let urlFrameName = v8Util.getHiddenValue(webContents, 'url-framename')
if ((disposition !== 'foreground-tab' && disposition !== 'new-window') ||
!urlFrameName) {
return
}
let {
url,
frameName
} = urlFrameName
v8Util.deleteHiddenValue(webContents, 'url-framename')
const options = {
show: true,
x: left,
y: top,
width: width || 800,
height: height || 600,
webContents: webContents
}
ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
event, url, frameName, disposition, options)
})
...
与新窗口的通信就是进程之间通信了,可以了解到不同窗口之间的通信就是要借助进程进行通信了.process对象对应的就是当前进程。在electron中是接触ipcMain与ipcRender进行渲染进程和主进程之间的通信,ipcMain与ipcRender.回到nodejs中进程通信是父子进程在(ipc)(Inter-process communication)上进行通信
所以先看一下process的文档中
process.send(message[, sendHandle[, options]][, callback])
/*If Node.js is spawned with an IPC channel,
the process.send() method can be used to send messages
to the parent process. Messages will be received as a 'message'
event on the parent's ChildProcess object.
*/
//接受信息
process.on('message', function(args){
});
再结合nodejs进程通信🌰和官方例子
这样就不难懂
ipcRender 中发送信息(直接理解成其是一个子进程与父进程Main通信)
//electron封装后的ipc api
ipcRenderer.send(channel[, arg1][, arg2][, ...])//异步信息发送
ipcRenderer.on(channel, listener)//监听信息
ipcRenderer.on(message,function(event,args){
//...
})
ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])//同步信息发送
//electron中 ipcMain
ipcMain.on(channel, listener)
ipcMain.on(message,function(event,args){
//event.sender(处理异步信息)
//event.returnValue
//this to the value to be returned in a synchronous message.(用于处理同步信息)
})