Windows下支持自动更新的Electron应用脚手架的方法


Posted in Javascript onDecember 24, 2018

前言

之前写过一篇关于 Windows 下通过 Electron 自带的 autoUpdater 实现应用自动更新的文章,很多小伙伴私信问我要具体实现代码,不过因为之前一直很忙(还有懒...)。

这两周正好周末比较空,除了在 github 上搭建了一个脚手架,还顺便把实现优化了一波,下面将会带着大家从零开始详细介绍实现过程,对小白也很友好的教程哦。

从零开始

进入你的工作目录,比如 d/workspace

# 目录 d/workspace
mkdir electron-demo # 新建文件夹 electron-demo
cd electron-demo # 进入文件夹 electron-demo
npm init # 初始化 npm,一路回车即可
npm i electron --save-dev # 安装 electron 依赖
touch main.js # 新建文件 main.js
touch index.html # 新建文件 index.html

现在你的文件结构如下:

|- electron-demo
 |- main.js # 空文件
 |- index.html # 空文件
 |- package.json
 |- package-lock.json # npm 自动生成的文件
 |- node_modules

确保 package.json 的name,version,description这三个字段都不为空,main 字段的取值为 main.js 。

{
 "name": "electron-demo",
 "version": "0.0.1",
 "description": "electron-demo",
 "main": "main.js"
}

主进程和渲染进程

Electron 应用分为主进程和渲染进程。渲染进程是直接与用户产生交互的进程,也就是我们看到的一个个窗口页面,而主进程主要负责控制应用的生命周期,负责各个渲染进程的通信等。

我们的主进程代码写在 main.js 中,所以首先在你心爱的代码编辑中打开 main.js,输入如下代码:

const path = require('path');
const url = require('url');
const {
  app,
  BrowserWindow
} = require('electron');

app.on('ready', () => {
  let win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      devTools: true
    }
  });

  win.loadURL(
    url.format({
      pathname: path.join(__dirname, 'index.html'),
      protocol: 'file:',
      slashes: true
    })
  );
});

app.on('window-all-closed', () => app.quit());

再打开 index.html,输入如下代码:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Hello World!</title>
</head>

<body>
  <h1>Hello World!</h1>
</body>

</html>

之后执行

# 目录 d/workspace/electron-demo
node_modules/.bin/electron .

不出意外的话你会看到一个弹出框,像这样:

Windows下支持自动更新的Electron应用脚手架的方法 

我们也可以把 node_modules/.bin/electron . 保存成 npm 脚本,方便以后调用。打开 package.json,添加如下内容:

"scripts": {
  "start": "electron ."
 }

以后只需要调用 npm start 即可。

到这里,我们已经有了一个最简单的 Electron 应用,如果你对继续开发应用本身更感兴趣的话,请移步Electron 官方文档,因为接下来我们会专注在怎么让这个应用实现自动更新。

自动更新

安装依赖

自动更新功能的实现依赖 electron-builder 和 electron-updater,所以我们需要先安装这两个依赖。

# 目录 d/workspace/electron-demo
npm i electron-builder --save-dev # 必须安装为开发依赖,否则打包会出错
npm i electron-updater --save # 必须安装为运行依赖,否则运行会出错

配置 package.json

为了配合打包 package.json 需要新增字段 build:

"build": {
  "appId": "com.xxx.app",
  "publish": [
   {
    "provider": "generic",
    "url": "http://127.0.0.1:8080"
   }
  ]
 },

同样为了执行方便,我们需要添加一个 npm 脚本,打开 package.json,添加如下内容:

"scripts": {
  "start": "electron .",
  "build": "electron-builder -w"
 }

以后只需要调用 npm run build 即可。

主进程和渲染进程

打开main.js,编辑后内容如下:

const path = require('path');
const url = require('url');
const {
  app,
  BrowserWindow,
  ipcMain 
} = require('electron');
const { autoUpdater } = require('electron-updater');
const feedUrl = `http://127.0.0.1:8080/${process.platform}`;

let webContents;

let createWindow = () => {
  let win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      devTools: true
    }
  });

  webContents = win.webContents;

  win.loadURL(
    url.format({
      pathname: path.join(__dirname, 'src/index.html'),
      protocol: 'file:',
      slashes: true
    })
  );

  webContents.openDevTools();
};

let sendUpdateMessage = (message, data) => {
  webContents.send('message', { message, data });
};

let checkForUpdates = () => {
  autoUpdater.setFeedURL(feedUrl);

  autoUpdater.on('error', function (message) {
    sendUpdateMessage('error', message)
  });
  autoUpdater.on('checking-for-update', function (message) {
    sendUpdateMessage('checking-for-update', message)
  });
  autoUpdater.on('update-available', function (message) {
    sendUpdateMessage('update-available', message)
  });
  autoUpdater.on('update-not-available', function (message) {
    sendUpdateMessage('update-not-available', message)
  });

  // 更新下载进度事件
  autoUpdater.on('download-progress', function (progressObj) {
    sendUpdateMessage('downloadProgress', progressObj)
  })
  autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
    ipcMain.on('updateNow', (e, arg) => {
      //some code here to handle event
      autoUpdater.quitAndInstall();
    })
    sendUpdateMessage('isUpdateNow');
  });

  //执行自动更新检查
  autoUpdater.checkForUpdates();
};

app.on('ready', () => {
  createWindow();

  setTimeout(checkForUpdates, 1000);
});

app.on('window-all-closed', () => app.quit());

index.html:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Hello World!</title>
</head>

<body>
  <h1>Hello World!</h1>
  <script>
    const { ipcRenderer } = require('electron');

    ipcRenderer.on('message', (event, { message, data }) => {
      console.log(message, data);
      switch (message) {
        case 'isUpdateNow':
          if (confirm('现在更新?')) {
            ipcRenderer.send('updateNow');
          }
          break;
        default:
          document.querySelector('h1').innerHTML = message;
          break;
      }
    });
  </script>
</body>

</html>

打包

npm run build

第一次运行会比较慢,运行结束后会在当前目录下新增一个 dist 文件夹,dist 的目录结构如下:

|- dist
 |- win-unpacked
 |- electron-autoupdate-scaffold Setup.exe
 |- electron-autoupdate-scaffold Setup.exe.blockmap
 |- electron-builder-effective-config.yaml
 |- latest.yml

win-unpacked 下是可执行文件,但是先别着急运行,我们还缺一个后台。

自动更新后台

聪明的你一定注意到,前面代码中我们有一个:

const feedUrl = `http://127.0.0.1:8080/${process.platform}`;

所以我们现在要做的就是一个可以接受这个请求的服务。

回到你的工作目录(d/workspace)

# 目录 d/workspace
mkdir electron-server
cd electron-server
npm init
npm i koa --save
npm i koa-static --save
touch server.js

打开 server.js,输入如下内容:

// server.js
let Koa = require('koa');
let app = new Koa();
let path = require('path');

app.use(require('koa-static')(path.resolve(__dirname + '/packages')));

let server = app.listen(8080, () => {
  let { address, port } = server.address();

  console.log("应用实例,访问地址为 http://%s:%s", address, port);
});

将之前打包出来的 dist 目录下的 4 个文件(除了 win-unpacked)拷贝到这边的 packages/win32 下(新建目录 packages/win32),之后

# 目录 d/workspace/electron-server
npm start

到此为止,我们的自动更新服务就搭建完成了,现在来一波测试吧。

测试

进入 electron-demo/dist/win-unpacked 找到可执行文件,双击运行,看到打开窗口的控制台中依次输出:

checking-for-update
update-not-available

进入 electron-demo,打开 package.json,把版本号改为0.0.2,重新打包后拷贝打包文件到自动更新后台目录(d/workspace/electron-server/packages/win32)。

进入 electron-demo,打开 package.json,把版本号改为0.0.1,重新打包后再次进入 dist/win-unpacked 目录,运行 exe,看到打开窗口的控制台中依次输出:

checking-for-update
update-available

并且出现弹窗提示「现在更新?」。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
出现“不能执行已释放的Script代码”错误的原因及解决办法
Aug 29 Javascript
js form action动态修改方法
Nov 04 Javascript
一个可以兼容IE FF的加为首页与加入收藏实现代码
Nov 02 Javascript
JQuery扩展插件Validate—6 radio、checkbox、select的验证
Sep 05 Javascript
Vue开发中整合axios的文件整理
Apr 29 Javascript
JS中使用gulp实现压缩文件及浏览器热加载功能
Jul 12 Javascript
JavaScript使用FileReader实现图片上传预览效果
Mar 27 Javascript
原生JS实现逼真的图片3D旋转效果详解
Feb 16 Javascript
JS使用栈判断给定字符串是否是回文算法示例
Mar 04 Javascript
JS实现li标签的删除
Apr 12 Javascript
JavaScript中Dom操作实例详解
Jul 08 Javascript
Jquery 获取相同NAME 或者id删除行操作
Aug 24 jQuery
如何使用electron-builder及electron-updater给项目配置自动更新
Dec 24 #Javascript
Vue.js组件高级特性实例详解
Dec 24 #Javascript
JavaScript模板引擎原理与用法详解
Dec 24 #Javascript
jQuery实现的简单日历组件定义与用法示例
Dec 24 #jQuery
原生js实现Flappy Bird小游戏
Dec 24 #Javascript
node错误处理与日志记录的实现
Dec 24 #Javascript
详解如何在vscode里面调试js和node.js的方法步骤
Dec 24 #Javascript
You might like
php+mysql开源XNA 聚合程序发布 下载
2007/07/13 PHP
destoon实现资讯信息前面调用它所属分类的方法
2014/07/15 PHP
php+mysqli使用面向对象方式更新数据库实例
2015/01/29 PHP
WordPress自定义时间显示格式
2015/03/27 PHP
PHP IDE PHPStorm配置支持友好Laravel代码提示方法
2015/05/12 PHP
php获取用户真实IP和防刷机制的实例代码
2018/11/28 PHP
限制文本字节数js代码
2007/03/06 Javascript
学习从实践开始之jQuery插件开发 对话框插件开发
2012/04/26 Javascript
JavaScript面向对象编程入门教程
2014/04/16 Javascript
JavaScript中的操作符==与===介绍
2014/12/31 Javascript
jQuery实现鼠标悬停显示提示信息窗口的方法
2015/04/30 Javascript
使用JQuery FancyBox插件实现图片展示特效
2015/11/16 Javascript
Node.js中使用socket创建私聊和公聊聊天室
2015/11/19 Javascript
jquery插件EasyUI中form表单提交实例分享
2016/01/11 Javascript
JavaScript字符串常用的方法
2016/03/10 Javascript
Ext JS框架中日期函数的用法及日期选择控件的实现
2016/05/21 Javascript
jquery实现跳到底部,回到顶部效果的简单实例(类似锚)
2016/07/10 Javascript
深入剖析Express cookie-parser中间件实现示例
2018/02/01 Javascript
vue中render函数的使用详解
2018/10/12 Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
2019/01/07 Javascript
基于 jQuery 实现键盘事件监听控件
2019/04/04 jQuery
细述Javascript的加法运算符的具体使用
2019/10/18 Javascript
jquery实现图片放大镜效果
2020/12/23 jQuery
python实现多线程抓取知乎用户
2016/12/12 Python
Python图像滤波处理操作示例【基于ImageFilter类】
2019/01/03 Python
python重试装饰器的简单实现方法
2019/01/31 Python
使用Python获取当前工作目录和执行命令的位置
2020/03/09 Python
HTML5+CSS3模仿优酷视频截图功能示例
2017/01/05 HTML / CSS
美国家居用品和厨具购物网站:DealsDot
2019/10/07 全球购物
畜牧兽医本科生个人的自我评价
2013/10/11 职场文书
白血病募捐倡议书
2014/05/14 职场文书
专题组织生活会方案
2014/06/15 职场文书
幼儿教师师德师风演讲稿
2014/08/22 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
全国法制宣传日活动总结2014
2014/11/01 职场文书
2015年团支书工作总结
2015/04/03 职场文书