张鑫旭:我是如何实现 Electron 的在线升级热更新功能的?

3,227 阅读5分钟
原文链接: www.zhangxinxu.com

by zhangxinxu from www.zhangxinxu.com/wordpress/?…
本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意。

通常electron打包出来的文件都很大,有40~50M,如果每次改动升级都要下载个完整版本,实际上是很烦的。

实际上,只要主线程没有发生变化,我们是可以直接在线热更新我们的electron应用的。

一、electron的热更新效果预览

下面几张图是我实现的带热更新功能的electron应用实际效果截图:

打开electron应用,此时会去检测线上是否有新版本,例如,我本地版本是1.2.2,然后线上版本是1.2.4,则会有这样的显示:

可升级提示效果

点击“新版功能”会显示最新版的升级描述,例如,这里点击后出现弹框信息:

新版功能弹框说明截图

点击红色的“升级”按钮,则直接请求线上的资源替换本地资源,完成升级(升级成功后刷新页面),升级效果参见下gif截图:

升级效果实时gif截图效果

二、electron的热更新原理说明

1. 我是直接使用github作为线上资源仓储的

当使用raw.githubusercontent.com作为请求域名,我们是可以直接获取资源内容的,例如,我们要获取一个路径为js/test.js的文件,则该文件完整地址为:

https://raw.githubusercontent.com/username/project-name/master/js/test.js

此时,我们就可以使用node.js的https.get()方法获取这个js/test.js完整内容了。

2. 我是借助package.json标记版本和更新内容的

之所以借助package.json,主要是被里面约定俗成的version版本关键字吸引,如果用户本地version版本比github项目线上version版本低,岂不就意味着可以进行升级。

于是,再把升级文件列表和更新信息一整合,就有了完整的升级数据了,如下截图示意:

升级描述和升级版本信息截图示意

3. electron的热更新原理说明

当每次我们的electron加载完毕之后,就会发送一个请求,去获取github项目上的package.json文件,主要是知道目前线上的版本是多少,然后和本地的package.json文件的version版本数据做比较。如果发现版本不一致,则说明有新版可以升级,于是让界面变成这样:

可升级提示效果

当我们点击“升级”按钮后,会把高于本地版本的需要更新的文件重新整合成一个新的完整的升级文件列表,然后依次从github上远程获取,存储在一个临时文件夹中,如果全部文件获取成功,再一并覆盖本地资源,全部覆盖完成后,刷新页面,完成升级。

以上就是完整的升级原理。

三、electron的热更新一些代码实现

electron热更新最大的难点应该是如何获取远程资源,我简单整理了下,希望能够对有需求的小伙伴有所帮助,由于ES6并未花时间学习,因此,相关JS还是ES5语法:

var https = require('https');

var getHttpsData = function (filepath, success, error) {
  // 回调缺省时候的处理
  success = success || function () {};
  error = error || function () {};

  var url = 'https://raw.githubusercontent.com/username/project-name/master/' + filepath + '?r=' + Math.random();

  https.get(url, function (res) {
    var statusCode = res.statusCode;

    if (statusCode !== 200) {
        // 出错回调
        error();
        // 消耗响应数据以释放内存
        res.resume();
        return;
    }

    res.setEncoding('utf8');
    var rawData = '';
    res.on('data', function (chunk) {
      rawData += chunk;
    });

    // 请求结束
    res.on('end', function () {
      // 成功回调
      success(rawData);
    }).on('error', function (e) {
      // 出错回调
      error();
    });
  });
};

然后,下面的事情就简单了,直接把请求的数据写入本地就可以了,举个简单的例子,一个index.html文件:

getHttpsData('index.html', function (data) {
  // 写入文件
  fs.writeFileSync('index.html', data);
  // 然后下一个文件获取并写入...
});

配合一些loading交互效果,就完成了完整的在线热更新功能。

四、结束语

上周六的作为嘉宾参见了腾讯2017 TFC前端大会,其中不少分享主题内容其实是不错的,但是效果却一般。主要在于犯了下面几个大型分享常见错误:
1. PPT文字小多,放置大段的代码,在大型会议场合,后排的根本就看不到内容,因此,只能玩手机,这和平时在团队或者学院内分享是不一样的;
2. 分享内容为中规中矩的流水陈述,大型分享和晋升汇报不一样,应该像电影一样,通过可以制造冲突和巧妙的内容剪辑,让分享更有吸引力,否则长途奔波+早起的听众很容易打瞌睡;
3. 一些不适用于大型分享的小技巧,例如,请问如何如何请举手,如果是中小型分享,或者当前氛围不错,这些技巧有助于增加互动,但是在如此宽广的场地,以及大多人听众不是很专注的情况下,这种策略就略显尴尬,因为一个问题出来会没有预想的互动场景出现。因此尽可能通过单向的肢体,语调,措辞以及干货的内容展示自身风采才是上策。

最后,奉上帅照一张:

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:www.zhangxinxu.com/wordpress/?…

(本篇完)// 想要打赏?点击这里。有话要说?点击这里

想找个师兄入门前端?不妨 ×