做者:钟离,酷家乐PC客户端负责人
原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-duan-kai-fa-shi-jian-fen-xiang-ru-keng-zhi-nan/
酷家乐客户端:下载地址 https://www.kujiale.com/activity/136
文章背景:在酷家乐客户端在V12改版成功后,咱们积累了许多的宝贵的经验和最佳实践。前端社区里关于Electron知识相对较少,所以但愿将这些内容以系列文章的形式分享出来。
系列文章:javascript
Electron所使用的技术栈(JavaScript、NodeJs、HTML、CSS)和web前端工程师完美契合。因而,愈来愈多的前端工程师,用Electron来开发桌面客户端的开发,我也是其中的一员。css
虽然Electron技术栈对前端工程师比较友好,可是概念较多,和web前端开发仍是有很大差异的,写个入坑指南但愿能帮助读者快速上手Electron。html
首先抛出一个问题,web应用是桌面客户端吗?显然不是。那么,问题来了,什么样的软件才是桌面客户端呢?咱们既然要从web前端转到客户端开发,那么就须要了解客户端,就像咱们当初了解web应用同样。前端
回到刚刚那个问题,桌面客户端有两个重要的特色:java
web应用有本身的GUI,必须在浏览器中执行,所以不是桌面客户端。linux
浏览器能直接运行在操做系统上,并且有本身的GUI,所以浏览器是桌面客户端。git
在刚刚接触Electorn的时候,文档看的我是眼花缭乱。在某个加班的深夜,我不由对天长叹:这个东西到底能干啥?github
这东西能干啥?在经历了Electron的反复摩擦以后,我总结了Electron的几个关键能力:web
NodeJs所有能力,与操做系统交互ajax
Electron提供的基础模块,主要与操做系统交互
Chromium提供的能力,主要提供GUI图形界面
若是用户安装了咱们的桌面客户端,那么咱们的软件在用户电脑上运行时,就有了很是大的权利,这是把双刃剑。
用户选择了咱们的软件,咱们也要对用户的电脑负责。能力越大,责任也就越大:
1.注意内存的占用,特别是chromium,简直是内存怪兽。能够经过os来获取用户电脑的配置,而后根据电脑的配置和可用资源,来制定合理的策略。
一旦被贴上【流氓软件】、【很差用】的标签,就很难再改变用户的印象了。
主进程:从整个应用启动到结束,该进程一直存在。主进程只有一个。
渲染进程:主进程可用建立/销毁渲染进程,所以渲染进程的生命周期是不固定的。渲染进程能够有多个。
在Electron的API文档中,会在文档顶部标识该模块在哪一个进程可用,例如:ipcRenderer
主进程 | 渲染进程 |
---|---|
控制app的生命周期,为app注册关键事件 | 解析HTML,渲染窗口内容 |
阻止一些默认行为,例如webContents的跳转、download事件的默认行为等等(在渲染进程没法作到) | 处理窗口的交互逻辑 |
建立BrowserWindow,也就是渲染进程。合理设置窗口的参数,控制窗口的生命周期(例如什么时候销毁窗口),决定BrowserWindow加载何处的HTML | 与主进程通讯,实现高级交互 |
咱们回顾一下刚刚讲到的执行流程,其中有一个有趣的点,就是Electron的窗口会加载一个HTML来渲染窗口的内容。
HTML,以及HTML加载的css、js文件,统称为前端资源
若是不加载HTML的,客户端还能用吗?不妨来试试
// main process const win1 = new BrowserWindow(); const win2 = new BrowserWindow();
上述代码在主进程中执行,建立了两个窗口,窗口并没加载HTML文件。可是窗口倒是真实存在的,带有系统标准的控制栏,可拖动,是货真价实的系统窗口!
咱们能够发现,前端资源和窗口是分离的。由主进程建立的的窗口(BrowserWindow),既是一个系统原生窗口,同时也是一个加载&渲染前端资源的容器
窗口一般会经过file协议和http(s)协议来加载前端资源,接下来咱们看看这两种方式的区别。
在Electron的官方入门例子中,就是经过file协议来加载HTML的
经过file协议加载HTML,不管有没有网络,均可以加载到HTML文件,这是file协议核心优点。缺点也比较明显:
经过http协议加载HTML,优势是能够随时经过web页面的部署,更新渲染进程的资源,而且在https协议下,你能够在页面中使用前端熟悉的ajax请求来获取数据。
固然,缺点也比较明显:
方便读者更好理解上文的内容,写了一个小demo,源代码地址 https://github.com/littlecold233/electron-demo,例子有如下特色:
forceQuit
这个变量来控制。const { app, BrowserWindow } = require('electron') async function main () { await app.whenReady(); let forceQuit = false; const majorWindow = new BrowserWindow({ title: '主窗口', width: 1000, height: 750, minWidth: 1000, minHeight: 750, backgroundColor: '#f2f2f2', }); // 主窗口 // 阻止标题更新 majorWindow.on('page-title-updated', (e) => { e.preventDefault(); }); majorWindow.on('close', (e) => { // 用户但愿退出的时候,不做处理,默认会销毁这个窗口 if (forceQuit) return; e.preventDefault(); // macOS全屏的处理 if (majorWindow.isFullScreen()) { majorWindow.once('leave-full-screen', () => { majorWindow.hide(); }); majorWindow.setFullScreen(false); } else { majorWindow.hide(); // 隐藏窗口 } }); // 点击dock打开主窗口 app.on('activate', () => { majorWindow.show(); }); // 用户使用cmd + Q、代码中调用app.quit等状况 // 此时用户但愿可以退出应用,所以将forceQuit改成true app.on('before-quit', () => { forceQuit = true; }); app.dock.setIcon('./img/icon.png'); // 在app打包后,这一句代码实际上是不须要的 majorWindow.loadURL('https://wx.qq.com'); // http协议加载前端资源,随便加载一个微信试试 // majorWindow.loadURL('file://index.html'); // file协议加载前端资源 } main();
在本地跑一下这个例子
欢迎你们在评论区讨论,技术交流 & 内推 -> zhongli@qunhemail.com