前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >electron 构建跨平台桌面应用

electron 构建跨平台桌面应用

作者头像
QQ音乐技术团队
发布2018-01-31 17:48:26
3.5K0
发布2018-01-31 17:48:26
举报
文章被收录于专栏:QQ音乐技术团队的专栏

昨日(2016.09.13)本文发表后,获得了一定的阅读和转发量,但经部分网友反馈和仔细审核后发现,在与 NW.js 对比的环节,言辞欠妥,且数据的真实性有待考究,特此将争议部分删除,同时借此诚挚地向 NW.js 的作者以及各位读者反馈表示感谢,期待更多深入的交流和分享,修订后的版本如下:

Stack Overflow 联合创始人 Jeff Wood 曾说过,任何一个能用 JavaScript 编写的应用系统,最终都必将使用 JavaScript 实现。

简介

Electron 是一款可以通过 Web前端技术 构建跨平台桌面应用的框架。其原名为 Atom Shell, 是 Github 社区原本为 Atom 编辑器设计的一个跨平台应用外壳,它将 Chromium 和 Node.js 的事件循环整合在一起,并提供了一些与原生系统交互的 API。

简单地说,通过 Electron,我们可以使用自己所熟悉的前端技术轻松构建出一款能运行在Windows, Linux 和 Mac 上的桌面级应用程序。

现阶段已有许多优秀的桌面应用都是基于 Electron 开发,其中如 Atom 编辑器,VS Code 和 Postman 等等都是我们所熟知的,下面列出这当中的部分应用,是不是看到了许多熟悉的图标呢?

Hello World

案例运行

使用下面三步即可构建最简单的 Hello World 桌面程序。

代码语言:javascript
复制
1. 克隆官方的例子
$ git clone https://github.com/electron/electron-quick-start

2. 进入项目目录
$ cd electron-quick-start

3. 安装项目依赖后执行该程序
$ npm install && npm start

运行效果如下:

案例分析

察看目录结构如下:

代码语言:javascript
复制
.
├── .gitignore    
├── index.html
├── LICENSE.md
├── main.js
├── package.json
├── README.md
└── renderer.js

主要分为三个部分:

  • package.json: 定义了项目的依赖以及程序的主入口文件 main.js。
  • main.js: 负责创建应用窗口,并赋予其与当前操作系统的原生GUI交互的功能。
  • index.html: 定义了页面的渲染内容,即 “Hello World” 字符串。

Electron 程序启动时,会产生两条进程,分别是主进程和渲染进程,main.js 脚本执行的环境就是主进程,负责管理和维护着渲染进程的生命周期,拥有绝大部分 node模块 的调用能力;而在 main.js 中创建的每一个窗体则对应着一个渲染进程,它们之间相互独立,且都具备部分 Node模块 的功能。

主进程与渲染进程的关系如下图所示,它们之间通过 IPC 模块进行消息交互,关于 IPC 模块的使用,下面会提到。

功能模块

这个部分将介绍 Electron 里面常用到的几个功能模块。

IPC

上面提到,Electron 中包含了主进程和渲染进程,事实上主进程就是一个后台进程,掌控着渲染进程的创建与销毁动作,且官方提供的绝大部分模块也只能在该进程中调用。

主进程与渲染进程之间的通信通过 IPC(进程间通信)模块完成,IPC模块可划分为 ipcMain 和 ipcRenderer 两个部分,其中 ipcMain 对应 主进程中的 IPC模块,而 ipcRenderer 则是在渲染进程中使用,下面直接看个例子:

main.js:

代码语言:javascript
复制
// 引入 ipcMain 模块
const ipcMain = require('electron').ipcMain;
// 监听 ‘blabla’ 通道,收到消息后输出,并向 'blibli' 通道发送消息
ipcMain.on('blabla', function(event, arg) {
    console.log(arg);
    event.sender.send('blibli', 'hello client!');
})

index.html:

代码语言:javascript
复制
// 引入 ipcRenderer 模块
const ipcRenderer = require('electron').ipcRenderer;  
// 向 'blabla' 通道发送消息
ipcRenderer.send('blabla', 'hello server!');
// 监听 ‘blibli’ 通道, 收到消息后输出
ipcRenderer.on('blibli', function(event,arg) {
  console.log(arg);
});

输出效果正如你所期望那样:

main.js:

代码语言:javascript
复制
hello server!

index.html:

代码语言:javascript
复制
hello client!

remote

上面提到了大部分模块只能在主进程中调用,为了突破这种限制,Electron 官方还提供了 remote 模块以简化进程间的通讯。

通过 remote 模块,渲染进程可以方便地引用主进程中的模块和全局变量等。

main.js:

代码语言:javascript
复制
global.person = {
  name: 'boxizen',
  sex : 'male',
  age : 24
}

index.html:

代码语言:javascript
复制
// 引用 remote 模块
const remote = require('electron').remote;
// 输出 main.js 中定义的 person 全局对象的 age 属性值
console.log(remote.getGlobal('person').age);

输出效果(index.html):

代码语言:javascript
复制
24

webview

webview 是个比较有趣的标签,可以将线上的页面嵌入进 Electron app 中,与 iframe 不同的是,webview 和应用运行的是不同的进程,不拥有渲染进程的权限。

下面将演示如何将微信网页版嵌入进 Electron 应用里,只需要简单的两步:

index.html:

代码语言:javascript
复制
<webview autosize="on" src="https://wx.qq.com/" style="display:inline-flex; width:1000px; height:764px"></webview>

main.js:

代码语言:javascript
复制
mainWindow = new BrowserWindow({width: 1000, height: 764, resizable: false})

效果图:

这样一个PC版的微信就大功告成了,实际上就是利用 webview 标签加载微信网页版的在线地址,再在main.js中调整窗体大小以适配网页版的微信,是不是很简单呢。

webview 对象中包含 insertCSS()executeJavaScript() 两个方法,表示可以插入样式代码和执行 js 脚本,这样我们就可以对加载页面中的样式及交互逻辑进行修改。默认的 webview 没有 node 功能,而如果设置了 nodeintegration 属性,它将整合node,拥有可以使用系统底层的资源。

此外 webview 中的 preload 属性允许在页面的脚本执行前预加载一个指定的脚本,下面我们利用该属性和 executeJavaScript() 方法实现 electron 版微信的未读消息角标展示。

index.html:

代码语言:javascript
复制
// 这里使用 preload 属性预加载了 badge.js 脚本
<webview id="foo" autosize="on" preload="badge.js" src="https://wx.qq.com/" style="display:inline-flex; width:1000px; height:764px"></webview>

var webview = document.getElementById("foo");      
  webview.addEventListener('dom-ready', function () {             
  webview.executeJavaScript('badge.get()');
});

badge.js:

代码语言:javascript
复制
// 引入 IPC 模块
const ipcRenderer = require('electron').ipcRenderer;

badge = {
  get: function () {  
      // 监听微信左侧面板节点变化
    $(".panel").bind('DOMSubtreeModified', function() {          
      var count = 0;       
      // 累加所有未读消息   
      $(".icon.web_wechat_reddot_middle").each(function () {
        count += parseInt(this.textContent);
      });
      // 通过 IPC 发送给主进程
      if (count > 0) {
        ipcRenderer.send('badge-changed', count.toString());
      } else {
        ipcRenderer.send('badge-changed', '');
      }
    })
  }
}

main.js:

代码语言:javascript
复制
const electron = require('electron');
const ipcMain = electron.ipcMain;
const app = electron.app

exports.init = function() {
    // 监听角标通道消息
    ipcMain.on('badge-changed', function (event, num) {
      app.dock.setBadge(num);
    });
}

效果图如下,可以发现 Electron 的 dock 角标显示的未读消息数(11)跟微信中面板中未读消息数量一致:

其他

当然 Electron 中还有许多实用的模块,如作为桌面应用必不可少的 MenuTray 模块、拥有调用当前操作系统功能的 Shell 模块、NW.js 中不具备的自动更新功能 - autoUpdater 模块、自动提交奔溃报告的 crashReporter 模块和全局快捷键模块 global-shortcut 等等,此处不做过多介绍。

打包构建

Electron 打包的方式有很多种,常见的有 electron-builder、electron-packager 和 asar几种,在这里我使用的是 electron-packager 作为应用的打包工具。

首先还是得先安装 electron-packager:

代码语言:javascript
复制
npm install electron-packager --save-dev 

然后在 package.json 中编写构建命令,下面生成了分别在 Windows 和 Mac 下的两条构建命令:

代码语言:javascript
复制
"scripts": {
    "start": "electron .",
    "build-win": "electron-packager . doubanFM --platform=win32 --arch=x64 --version=1.2.6 --icon=./fm.ico --overwrite",
    "build-mac": "electron-packager . doubanFM --platform=darwin --arch=x64 --version=1.2.6 --icon=./fm.icns --overwrite"
  },

执行构建命令, done!

代码语言:javascript
复制
npm run build-mac

最后贴一张最近利用 Electron 构建的桌面版豆瓣FM的截图:

参考资料:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 QQ音乐技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • Hello World
    • 案例运行
      • 案例分析
      • 功能模块
        • IPC
          • remote
            • webview
              • 其他
                • 参考资料:
            • 打包构建
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档