使用Electron开发桌面级程序——J.A.R.V.I.S诞生记

2019-06-11 16:55:05 浏览数 (1)

那一天我二十一岁,在我一生的黄金时代,我有好多奢望。我想爱,想吃,还想在一瞬间变成天上半明半暗的云,后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消逝,最后变得像挨了锤的牛一样。可是我过二十一岁生日时没有预见到这一点。我觉得自己会永远生猛下去,什么也锤不了我。

现在是凌晨一点,可能是在夜里的时候人会变得比较感性,所以突然想到了王小波在黄金时代中写下的这段话,没有理由的在这篇技术文章中将它作为引言。希望大家在自己的黄金时代永远的生猛下去,什么也锤不了你。

书归正传,咱们上回书说到在我的第一版小程序发布系统被服务器拍倒在沙滩上后,我把目光从web转移到了app上,并准备使用Electron来构建一套app安装在电脑上用来解决服务器不支持部署小程序开发者工具的坑,接下来我将此次开发过程的思考和问题进行总结,从多个角度来介绍本项目。

J.A.R.V.I.S是做什么的?

它是一个安装在Mac或Windows上的app程序,可以随时从Git上拉取最新代码选取分支和tag并自动打包构建不同环境上传至小程序后台的发布系统。

为什么叫J.A.R.V.I.S?

老贾是唐尼的智能管家,项目启动的时候正值复联四热映,主要是为了纪念一下唐尼吧,在星期五和Jarvis两个名字中犹豫了好久,最后还是觉得Jarvis比较酷一点。嗯,就是这么随意。

设计思路

工作原理

electron本质上就是一个将web打包成桌面应用的 Node. js 的变体,在开启app的同时就会启动一个node服务,通过node可以实现很多前端无法实现的事情,一个发布系统整个流程都是千篇一律的,无非就是拉代码、拉分支、切分支、构建开发包、上传后台。其中拉代码、切分支、构建这种平时在命令行内进行的操作,可以将它交给nodeJs提供的child-process衍生子进程的功能进行不同目录下的shell脚本执行,最关键的上传则需要通过node请求微信开发中工具提供的api为渲染层提供上传接口进行相应操作。最后将electron项目打包为app,分别装在开发者的电脑上就可以实现一个基础版的小程序上传系统。

工作流程

配置

第一次使用需要先进行基础配置,将本机用户名、项目地址、开发者昵称一并保存到本地Stroage,为后续操作提供基础信息。保存的同时将项目拉取到本地的Applications目录中并新建一个jarvis目录,此目录用来保存以后所有需要构建的小程序项目,此时jarvis目录作为一个黑盒子,所有的信息都是从git拉下来的最新提交,与本地项目的开发代码会形成隔离,你的本地任何代码改动操作都不会影响到盒子内项目的信息,除非你进行了commit。

打包构建

切换分支

配置完基础信息后调用gitlabApi拉取该项目的分支和tag信息,渲染到下拉列表选择切换本地分支,同时在面板展示分支的基础信息,项目名称、当前分支名称、提交时间、提交描述、提交成员、提交id......

项目编译

接下来需要填写本次上传的版本号和版本描述并选择打包环境,然后进行项目构建。这里选择环境选择的是需要打包项目的根目录中的构建命令,比如我的小程序项目使用gulp构建,gulpfile中定义了四种打包命令,那么在点击开始项目构建后,程序会自动切换到黑盒中的项目根目录下执行对应命令并打包为dist文件。

上传

打包完之后的文件通过微信官方提供的http调用接口,先获取到开发者工具在本地的端口号文件,通过调用upload的api拼接端口号、项目路径、描述、版本号进行上传。上传成功后在面板上展示上传信息和上传状态并且通过钉钉群同步推送上传消息,包含发布版本、描述、发布人,最后在微信公众平台选择设置体验版。到此,一个完整的编译打包上传流程全部完成。

谈谈基础架构

整体使用vue-electron框架,分为五个大模块

  • dist——src的输出目录
  • src--开发目录
  • static——静态资源文件目录
  • build——打包文件目录
  • .electron-vue——webpack配置目录

.electron-vue——webpack配置目录

此目录下保存着不同的webpack配置文件,使用vue-loader、babel-loader、url-loader、vue-html-loader、post-css等插件使项目成为支持解析.vue文件,可使用高级js语法的现代化工程,并且会将开发目录打包为标准的electron项目。

dist electron输出目录

通过webpack将项目打包为一个electron的标准项目,输出到dist目录下,package.json将会以此目录下的mian.js作为入口文件进行运行。

src——开发目录

src作为核心内容,包含三大部分main(electron主进程文件目录)、render(前端渲染层页面——vue element)、service(后端提供服务接口——express)。

main作为一个桥梁的存在,链接着渲染层和服务端进程。其中service-main.js作为service中express的的启动文件导出,并在main/index.js中与electron同时启动,index.js为启动electron的核心文件,最后会被webpack编译输出到输出目录下——dist/electron/main.js

render负责前端页面的可视化渲染,使用vue element可以快速的构建出一套现代化的界面,某些情况下也可能会与原生app进行通信,如去除默认边框、自定义快捷命令等,所以渲染层常用的一个方法就是ipcRenderer,通过ipcRenderer可以与electron进行通信调用electron提供的一些原生api。

示例(关闭、放大、缩小)

这是vue定义的点击事件,通过发送不同的参数与electron的mian进行交互。

main.js负责监听通信并执行动作

示例(解决打包后无法复制粘贴的问题)

代码语言:javascript复制
 if (process.platform === 'darwin') {    const template = [      {        label: "Application",        submenu: [          { label: "Quit", accelerator: "Command Q", click: function() { app.quit(); }}        ]      },       {        label: "Edit",        submenu: [          { label: "Copy", accelerator: "CmdOrCtrl C", selector: "copy:" },          { label: "Paste", accelerator: "CmdOrCtrl V", selector: "paste:" },        ]      }    ];    Menu.setApplicationMenu(Menu.buildFromTemplate(template))  } else {    Menu.setApplicationMenu(null)  }

service为分为rutes、views、app.js三部分,rutes负责整个前端页面提供调用接口,app.js负责服务的启动和接口路由的注册,view内使用pug模板承载一些异常状态的访问页面。

示例(实现分环境打包接口)

这里需要注意一下,这个接口的实现是非常灵活的,需要根据你当前项目的编译文件进行配置,比如我的项目开发时使用gulp打包编译环境到dist,其编译命令分别为:

  • gulp build:Dev(联调环境)
  • gulp build:Test(测试环境)
  • gulp build:Slave(预发布环境)
  • gulp build:Prod(线上环境)

那么同理,配置好dist输出文件目录,收到请求后执行事先实现好的shell命令即可完成打包这一步,如果你不太了解环境编译打包这块内容,可以参考我之前的一篇文章"《武装你的小程序——开发流程指南》"

代码实现

build 打包app目录

 build是app打包完成后的输出目录,这个文件可以存放你的项目图标,打包的时候electron会默认在这个目录下找图标,如果找不到就会使用electron默认图标。

使用electron遇到的问题

  • 官方强烈推荐使用yarn安装依赖,淘宝镜像安装的依赖会在打包的时候导致超级多的未知bug!!!比如我一不小心使用了cnpm安装了elemnent-ui最后打包导致无法解析该模块,只能删除node-modules重新使用yarn安装。
  • error:Cannot assign to read only property 'exports' of object '#<Object>' 在express项目里使用了model.exports方式导出模块,但webpack 2中不允许混用import和module.exports 解决办法:

1.解决办法就是统一改成ES6的方式编写即可. import {a} from './a'; export default a;

2.引入插件transform-es2015-modules-commonjs yarn add babel-plugin-transform-es2015-modules-commonjs 然后在 babelrc中配置 { "plugins": ["transform-es2015-modules-commonjs"] } 即可解决

  • 如果在electron中使用了child_process去开启一个子进程执行shell的话,像是gulp,npm这种在开发环境可以正常执行,但打包app后node执行的环境变量就会被更改,导致执行失败,可以将process.env.PATH手动更改为process.env.PATH =':/usr/local/bin'即可。
  • 打包的app图标不是自己配置的图标?

脚手架的pacage.json有三个字段

你可以在这里配置你的项目图标。

项目展望

当前项目已经可以在公司内部的生产环境中使用,但与内部项目耦合严重,不够灵活,同时还有一些未知的问题和不足,我会在后续慢慢完善和优化,待解耦完成代码足够健壮的情况下会选择将项目代码开源出来,下面列出后续将要实现的功能。

  1. 项目管理器功能,可配置多个不同项目分别进行打包上传。
  2. 高度自定义的配置信息:gitlab的token、钉钉机器人的token、不同项目的打包执行脚本、不同的环境配置。
  3. 支持自定义分支列表而不是一次全部拉取出来,这对一些拥有超多的分支大型项目来说是不灵活的。
  4. 除了接口的shell脚本执行结果外打包后的验证功能,可以通过读取部分差异化文件进行比对打包结果。
  5. 同时支持支付宝小程序的上传功能。

结语

经过两个多月的空闲时间开发,期间算上demo做了三个版本,从layui express的前后端耦合版的1.0.0版本demo,到分离前后端分离的1.1.0的初版一切完成准备部署线上开发环境,因为前期思考的一些失误导致项目部署失败,再到从web转移到使用electron开发app安装在本地的1.2.0版本这个过程中收获满满,这个过程使我在思考问题和代码设计、项目架构的搭建各个方面都有了一个全新的认识,与此同时也学习到了一些新的技术框架,再此还要感谢同事大佬们的帮助为我提供各种思路和技术支持。

现在是凌晨四点钟,写不动了两个眼皮已经开始打架了,你看过北京凌晨四点钟的太阳么?emmm....根本就没有太阳,可能洛杉矶天亮的比较早,真羡慕科比大佬。今天是周六可以睡个懒觉起床吃饭打农药,熬夜的瘾是戒不掉了,但还是奉劝大家不要熬夜了,因为夜熬得太烂了就不好吃了。

0 人点赞