看见 Electron 教程,我啪一下就进来了,很快啊!

1,383 阅读9分钟

朋友们好啊,我是晓黑板前端团队的何锦余,刚才有个朋友问我,“何老师,发生甚么事了?”,我说怎么回事,给我发了一个链接。我一看,喔!原来是前些天有几个年轻人,做了一个很不错的东西,写了一系列介绍 Electron 的文章。有一个说我们这个写了这么长时间了,在我们自己的晓黑板 App 上也用上了,效果很好啊,何老师你能不能用用看,看看有甚么地方可以再改进改进。

我一开始说你们这个东西啊,不好用。还不如我自己照着官网重头写。后来这些年轻人不服气啊,给了我一个链接,我点进去,先给了个 star,想着年轻人嘛,需要鼓励一下啊。然后我就拉下了代码,装完了依赖,然后运行 npm start

不一会儿功夫,蹦出来一个很好看的命令行页面啊。

我看可以让我输入 open api,我就试了一下。这一试不要紧啊,啪一下,一个窗口打开了,很快啊。我一看这界面,方方面面的东西都介绍了啊。这几个年轻人乘机问我,何老师,我们这个怎么样?不比官网的介绍差吧,要不要实战一下,上手用一用。

三生万物

这几年开发,总结出了一个套路,一个东西的诞生,要经历三个步骤,我称之为“接”、“化”、“发”,下面我就一步步的去演示一下。

根据 electron-playground 的开发步骤,我很快的就初始化好了项目。目录结构如下:

.
├── index.js // 主文件
├── node_modules
│   ├── @electron
│   └── ...
├── package.json
├── src
│   └── index.html // 页面渲染文件
└── yarn.lock

安装 electron 的时候,有可能会发现网速太慢。这个时候可以配置一下环境变量,使用淘宝源下载。

  export ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/

执行 yarn start(提前配置好此命令对应为 electron .),即打开了如下页面。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V1 切换到名为 V1 的 Tag 就能看到了,仓库地址点击这里

但是这样肯定不够啊,于是跟着教程走,我又引入了 TypeScript 和 Webpack。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V2 切换到名为 V2 的 Tag 就能看到了,仓库地址点击这里

继续跟着配置了 webPreferences.preload,确保在页面运行其他脚本之前预先加载 preload.js,而 preload.js 里面给页面注入了 JSBridge,页面中可以通过调用其中的方法来实现 Electron 提供的能力。下图中点击 Get App Info 按钮获取到了应用的信息。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V3 切换到名为 V3 的 Tag 就能看到了,仓库地址点击这里

继续跟着 playground 走,我又配置好了 React 环境,这下意味着我们可以用 React 来编写页面,并且赋予它原生应用才具备的能力。弄到这里,我突然想到,Electron 就是桌面版的 Cordova 嘛,Electron 使用 Chromium 来渲染页面,桌面系统的优势相对于移动端来说可是太明显了,在移动端渲染 Web 页面的性能不如原生 App 的问题在桌面系统上也几乎不存在,利用 HTML/CSS/JavaScript 快速构建页面简直不要太爽。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V4 切换到名为 V4 的 Tag 就能看到了,仓库地址点击这里

因为每次都需要到 renderer 目录里面启动 Web 开发环境,然后还要启动 Electron 的 JavaScript 开发环境,最后还需要启动 Electron 自己的打包命令。所以简单的整合了一下,现在只需要执行 npm run dev,等待 Web 端和 Electron JavaScript 打包完成,然后点击 VSCode 下方的 Launch Program 即可(根据教程配置了 .vscode/launch.json,可以在 VSCode 下很方便的进行开发和调试工作)。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V5 切换到名为 V5 的 Tag 就能看到了,仓库地址点击这里

我觉得我已经做好了基础准备,接下来准备开始从 playground 中选择几个点,来做一个桌面应用出来。这里不得不夸一句,playground 中的知识点实在太多了,而且这几个年轻人还在持续的更新当中。我这里准备选择其中的“协议”和“下载管理器”两项,来做一个指定协议地址的下载工具。类似迅雷的下载地址 thunder://xxx,我决定给我的应用取名叫“掩耳”(灵感来源迅雷不及掩耳),下载地址的协议格式为 ear://xxx

接(接需求)

先整理一下我目前想到的需要实现的需求:

  • 下载功能的实现;
  • 支持从浏览器中点击 ear://xxx 链接,可以唤起“掩耳”客户端;

首先,还是引入 antd 来快速实现页面吧,怎么引入就按下不表了,毕竟 renderer 目录里面就是个普通的 React Web 项目,平时怎么开发现在还是怎么开发。

很快啊,我们用 antd 就快速实现了项目的界面。

化(化零为整,拆分组件)

我们是怎么做的呢,基本就是吧页面拆分一下,主要分为三块:

  • 页面头部,对应 AppHeader 组件;
  • 页面内容部分,对应 AppContent 组件,以及显示的下载/已完成列表组件;
  • 下载的弹窗,对应 DownloadModal 组件;

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V6 切换到名为 V6 的 Tag 就能看到了,仓库地址点击这里

注册协议

接下来开始实现功能了哈,先实现从浏览器打开 ear:// 协议的链接可以唤起应用的功能,很简单啊这个,playground 上都附上源码了,直接搬运过来。修改一下协议为 ear 即可。为了让文章看起来更充实一点,我还是附一下关键代码吧。electron-playground 这个项目真是为我们做得太多了。想试试 Electron 的同学们真是有福了。

// 注册自定义协议
function setCustomProtocol() {
  const agreement = 'ear' // 自定义协议名
  let isSet = false // 是否注册成功

  app.removeAsDefaultProtocolClient(agreement) // 每次运行都删除自定义协议 然后再重新注册
  // 开发模式下在window运行需要做兼容
  if (process.env.NODE_ENV === 'development' && process.platform === 'win32') {
    // 设置electron.exe 和 app的路径
    isSet = app.setAsDefaultProtocolClient(agreement, process.execPath, [
      path.resolve(process.argv[1]),
    ])
  } else {
    isSet = app.setAsDefaultProtocolClient(agreement)
  }
  console.log('是否注册成功', isSet)
}

然后我们需要获取到这个链接,后续对它进行下载处理,当然,这部分的代码也有了,这里我就不粘贴上来了。下图中可以看到我们已经拿到了自定义链接 ear://xxx

写完这里不禁感叹,难怪牛顿说“如果我的开发效率能更高,那是因为站在了巨人的肩膀上”,如果没有这么好的开源项目,我得浪费多少时间来做这些东西。

下载功能实现

接下来开始实现下载功能,说出来你可能不信,Playground 中对下载这一块做了个详细的说明,甚至还附带了一个 demo!

看了一下,基本思路就是通过 downloadURL 方法触发下载,通过监听 will-download 事件获取下载的信息。

// 触发下载
win.webContents.downloadURL(url)

// 监听 will-download
// downloadItem 会触发 updated 和 done 事件,此时可以通过 downloadItem 上的 getTotalBytes、getReceviedBytes 等方法获取下载对象的基础信息
session.defaultSession.on('will-download', (event, downloadItem, webContents) => {})

大致的实现了一下,最终的效果如下,最基础的下载功能已经实现,由于我发现 Electron Playground 的关于下载这一块的功能实现的过于完善,所以我就不再做多余的工作了,有兴趣的同学直接去看看这群年轻人的代码就好了。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V7 切换到名为 V7 的 Tag 就能看到了,仓库地址点击这里

发(发散思维,实现我们的小彩蛋)

最后,其实文章到这里已经差不多了,这其实是我第一次接触 Electron,之前仅仅只会这个单词的拼写,然后跟着我们的小伙伴们写的教程 Electron Playground,很顺利的就搭建了一个 Electron App,我还是很开心的,希望感兴趣的同学也可以去学习一波。

然而,前面说了要实现 ear:// 协议地址的下载,我还是想做一下,好给这个小 demo 画上一个圆满的句号。接下来说一下我的实现思路,因为这里的下载实际上是 Chromium 提供的能力,所以本质上还是走的 http(s):// 协议。所以我想,对 http(s):// 地址做一个对称加密成 ear://,然后下载的时候再解析回 ear:// 就好了。为什么要做这看起来脱裤子放屁的事情呢?实际上是为了让文章内容看起来丰富一些。为什么要做这件事情呢?因为想必各位在微信、微博上都见过屏蔽链接的事情,如果我们不使用传统的 http(s):// 链接,自然就不会被和谐了。

一顿操作,最终我们成功的在浏览器端输入 ear:// 链接并成功的下载了。

对了,代码我上传到了 GitHub 上,如果你不嫌烦的话,可以克隆代码到本地,然后执行 git checkout V8 切换到名为 V8 的 Tag 就能看到了,仓库地址点击这里

好啦,如果大家对 Electron 感兴趣的话,可以试一试在自己的机器上跑一下喔,送给大家一个链接不是彩蛋用来测试。ear://VWSpnQ90LVlbcD+uABt8VHhKBSgM06XPccnLo5zVSgDJd67zNGf1afwD5pmMdt/x,祝大家学习快乐,玩得开心。

再见👋

对了,我们已经有了一些介绍 Electron 的精美文章,都是满满的干货的那种,欢迎大家点击关注 Electron Playground 专栏,我们的开源项目地址在这里,点 star,不迷路。

最后,我们是好未来·晓黑板前端团队。下次再见。👋