Electron系列文章-主进程与渲染进程

本文主要讲解上一章节提到的主进程与渲染进程的概念,以及它们是如何被使用的javascript

若是对文章的内容有任何疑问或吐槽,请直接在下方评论,你们共同窗习和改进html

阅读时间:约4minjava

主进程与渲染进程

咱们来回顾一下,程序目录结构章节中所给出的基本目录结构node

app----------------------------应用程序代码目录
├─main.js----------------------程序启动入口,主进程
├─common-----------------------通用模块
├─log--------------------------日志模块
├─config-----------------------配置模块
├─ipc--------------------------进程间模块
├─appNetwork-------------------应用通讯模块
└─browserWindows---------------窗口管理,渲染进程
    ├─components---------------通用组件模块
    ├─store--------------------数据共享模块
    ├─statics------------------静态资源模块
    └─src----------------------窗口业务模块
        ├─窗口A----------------窗口
        └─窗口B----------------窗口
复制代码

在上面的目录结构中,main.js就是咱们所说的主进程。而经过browserWindows目录下窗口文件建立的进程,咱们称之为渲染进程。渲染进程须要经过主进程来建立,并被主进程所管理。这里你们可能会有疑问了,什么是进程?为何要分主进程和渲染进程呢?web

进程的概念

计算机进程相关的知识在搜索引擎中能够搜到不少,咱们这里不作过多的讲解。读者能够把进程理解为操做系统管理应用程序的基本单位,每一个进程之间的资源是不能直接共享的。打开操做系统的任务管理器,咱们能够看到当前操做系统都有那些进程,以下图api

主进程

回顾以往的web开发,咱们的代码,不管是HTML、CSS仍是Javascript,都是运行在浏览器的沙盒中的,咱们没法越过浏览器的权限访问系统自己的资源,代码的能力被限制在了浏览器中。浏览器之因此这么作,是为了安全的考虑。设想一下,咱们在使用浏览器的时候,会打开各式各样不一样来源的网站,若是JavaScript代码有能力访问并操做本地操做系统的资源,那将是多么可怕的事情。你在某天不当心打开了一个恶意的网站,可能你存储在硬盘上的文件就被偷走了(都用不着去修电脑)。浏览器

但咱们要开发的是桌面应用程序,若是没法访问到本地的资源确定是不行的。Electron将nodejs巧妙的融合了进来,让nodejs做为整个程序的管家。管家拥有较高的权限,能够访问和操做本地资源,使用本来在浏览器中不提供的高级API。同时管家也管理着渲染进程窗口的建立和销毁。因此,咱们将这个管家称之为主进程。在使用Electron开发的程序中,会使用main.js做为程序的主入口,该文件内代码执行的内容,就是主进程中执行的内容。安全

下面咱们一块儿来看看主进程中通常都作些什么。架构

//main.js

var electron      = require('electron');
var app           = require('electron').app;

//初始化
app.on('ready', function(){

    try{      
        //app ready
    }catch(err){
        log.error(err);
    }
});

复制代码

上面是一个最简单的main.js例子。在例子中,咱们首先引入了electronelectron.app模块。electron.app对象控制着整个程序的生命周期,在这咱们只注册了生命周期中的ready事件,当ready事件被触发的时候,表示整个程序已经初始化完毕,能够开始进行建立窗口等业务逻辑了。app

在现实的应用中,主进程的代码远比上面的例子复杂的多。有许多需求特性的实现都是在主进程中完成,下面举个例子进行讲解。

程序互斥

在某些场景中,应用程序被要求在系统中只能同时开启一个。因此当某个应该已经在系统中运行时,若是再次双击应用icon,程序应该将本身退掉,或者是把以前打开的程序退掉。

(function(){

  app.makeSingleInstance(singleInstanceCallBack);

  function singleInstanceCallBack(commandLine, workingDirectory){

    console.log('command line: ', commandLine);
    console.log('working directory: ', workingDirectory);

    app.exit(0);        
  }
})();

复制代码

这里使用的是app.makeSingleInstanceapi实现的这个功能。singleInstanceCallBack函数是当第二个实例启动时,第一个实例执行的回调,因此singleInstanceCallBack里面使用的app实际上指向的是先打开的实例(刚接触这个api的时候确实有点绕),上面的代码中,singleInstanceCallBack执行时,调用了app.exit方法退出了先打开的程序。那咱们如何去判断当前是第二个实例呢?其实,makeSingleInstance的返回值是一个boolean类型的值,为true时表示当前是第二个实例。若是需求是想让第二个实例退出,则在当前的做用域中直接调用app.exit便可。

渲染进程

Electron集成了Chromium来展现窗口界面,窗口中所看到的内容使用的都是HTML渲染出来的。 Chromium自己是多进程渲染页面的架构(在默认状况下,Chromium的默认策略是对每个tab新开一个进程,以确保每一个页面是独立且互不影响的。避免一个页面的崩溃致使所有页面没法使用),因此Electron在展现窗口时,也会使用到Chromium的多进程架构。而这种多进程渲染架构在Electron中,就被称之为渲染进程(render process)。

在Electron中,每建立一个新的窗口,都是一个独立的进程。

//main.js
const {BrowserWindow} = require('electron');
const window1 = new BrowserWindow({width: 200, height: 200})
const window2 = new BrowserWindow({width: 200, height: 200})

window1.loadURL('https://baidu.com');
window2.loadURL(`file://${__dirname}/index.html`)

复制代码

在上面的代码中,咱们建立了2个窗口,window1window2。这两个窗口就是互相独立的进程。window1窗口内容指向的是百度首页,window2窗口内容指向的是咱们本身开发的html页面。在index.html中,咱们能够像开发正常的web网页同样,开发窗口内容。如下是index.html的一个示例

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,user-scalable=0">
    <title>main page</title>
</head>
<body>
    <div id="app">Hello World</div>
    <script type="text/javascript" src="mainPage.js"></script>
</body>
</html>
复制代码

在介绍主进程的篇幅中,咱们说到只有主进程才有获取本地资源的权限。实际场景中,有时须要将主进程中获取的本地数据在窗口中展现出来,该怎么实现呢?

在下一章,咱们会重点讲解主进程与渲染进程之间如何通讯的知识。

相关文章
相关标签/搜索