自己动手开发更好用的markdown编辑器-06(自动更新)
2015-05-12 15:53
459 查看
这里文章都是从个人的github博客直接复制过来的,排版可能有点乱. 原始地址 http://benq.im/2015/05/12/hexomd-06/
文章目录
1. 自动更新方案
2. 实现
2.1. 安装依赖模块
2.2. 自定义package.json
2.3. updater.js
2.4. 绑定更新按钮
3. 总结
4. 附件
上一篇我们实现了
今天将实现
对于不想看如何实现的朋友,直接下载打包好的程序就行,以后更新可以点击软件右上角的第一个按钮即可(手动).
所以做这个软件的自动更新的时候,我用了更为简单粗暴的方案:将需要更新的文件打包成zip文件,直接下载并解压覆盖即可.
将
更新的流程为 :
这里我直接用7z.exe,反正也不大,也可以使用一些开源的node压缩模块.
先在modules/directives增加新的directive
然后将index.html上的更新按钮与directive绑定
别忘了引用
无法自动删除新版本不需要的文件
以后如果程序大了,更新补丁每次都全量打包会导致更新很慢
更新后不会自动重启软件.
更好的方案是自动根据git的提交信息生成更新列表,并且根据版本号管理.
接下来的计划:
云同步.
插件机制
表情插件.
项目地址
文章目录
1. 自动更新方案
2. 实现
2.1. 安装依赖模块
2.2. 自定义package.json
2.3. updater.js
2.4. 绑定更新按钮
3. 总结
4. 附件
上一篇我们实现了
粘贴上传图片功能.
今天将实现
自动更新的功能,有了这个功能以后我再发博客就不需要每次都把最新的程序重新打包上传了.
对于不想看如何实现的朋友,直接下载打包好的程序就行,以后更新可以点击软件右上角的第一个按钮即可(手动).
自动更新方案
在做上一个软件Gungnir的时候,为了可以显示更新进度,自动更新的方案是列出所有需要更新的文件,然后自动下载每个文件并覆盖,但是在需要更新一些node模块(文件一般都很多)时就相当麻烦了,有一个文件传输失败就会导致更新出错.实现起来相当麻烦,而且也并不能带来什么优势.所以做这个软件的自动更新的时候,我用了更为简单粗暴的方案:将需要更新的文件打包成zip文件,直接下载并解压覆盖即可.
实现
自动更新作为较单独的功能模块,我把全部代码放在modules/updater.js,这里就不把全部代码贴出来了,需要的自己点链接看,里面有注释. 我只讲一些实现细节.安装依赖模块
首先是安装两个新增了的node模块依赖when和
bufferhelper,第一个是
promise模块,第二个看名字就知道,无须解释.
1 | npm install when --save |
1 | npm install bufferhelper --save |
7z.exe放到软件根目录备用
自定义package.json
增加了updater配置节点,配置最新的版本号version和对应的补丁文件地址
package,由于我这个软件功能很少,代码并不多,因此我现在每次更新都是包含之前所有补丁的文件打包,加起来也才1m多,这样实现比较简单,只要下载最新的包即可.
1 2 3 4 5 | ... "updater":{ "version":"0.6.0.1", "package":"http://7xit5q.com1.z0.glb.clouddn.com/update.zip" } |
updater.js
updater.js里实现了
hmd.updater模块,包含4个方法
1 2 3 4 5 | //配置文件,用于判断是否有新版本 var packageFile = 'https://raw.githubusercontent.com/benqy/hexomd/master/package.json', //当前程序的运行目录 execPath = require('path').dirname(process.execPath), //补丁文件存放目录 updatePath = execPath + '\\update', fs = require('fs'), util = require('./helpers/util'), when = require('./node_modules/when'); var checkUpdateTimer; hmd.updater = { //下载指定url的内容并返回promise对象 get: function (url) { ... }, //检查更新 checkUpdate: function () { ... }, //下载补丁包 update:function(packageUrl){ ... }, //安装补丁包 install: function () { ... } }; |
checkUpdate检查是否有更新 >
update下载补丁包 >
install安装补丁包
get方法里要注意的是下载下来的内容要判断是否经过
GZIP压缩,如果是,则要用node自带的
zlib解压.
1 2 3 4 5 | ... req = protocolModule.get(urlOpt, function (res) { //是否经过gzip压缩 var isGzip = !!res.headers['content-encoding'] && !!~res.headers['content-encoding'].indexOf('gzip'); ... if (isGzip) { require('zlib').unzip(buffer, function (err, buffer) { gzipDeferred.resolve(buffer); }); } else { gzipDeferred.resolve(buffer); } ... return deferred.promise; |
checkUpdate方法里先下载线上的
package.json文件与本地进行比较,如果版本号不一致,则提示用户更新.如果用户选择更新,则下载package.json到本地,然后调用
update方法下载补丁
1 2 3 4 5 | checkUpdate: function () { hmd.msg('===正在检查更新==='); //超时检查 checkUpdateTimer =setTimeout(function(){ hmd.msg('===更新失败,可能github被墙了===', hmd.MSG_LEVEL.error); }, 10000); var locPackage = require('nw.gui').App.manifest; //获取版本信息和更新文件列表 hmd.updater.get(packageFile) .then(function (packageData) { clearTimeout(checkUpdateTimer); packageData.text = packageData.buffer.toString(); if (!packageData.text) return; var remotePackage = JSON.parse(packageData.text); if (remotePackage.updater.version != locPackage.updater.version){ if (confirm('是否更新到最新版本:' + remotePackage.updater.version)) { //如果update目录不存在则创建 if (!fs.existsSync(updatePath)) { util.mkdir(updatePath, true); } //保存最新的配置文件 fs.writeFileSync(updatePath + '\\package.json', packageData.buffer); //下载补丁包 hmd.updater.update(remotePackage.updater.package); } } else { hmd.msg('当前版本:' + remotePackage.updater.version + ',已经是最新版'); } }); } |
update方法下载补丁包到
update目录,然后调用
install安装补丁
1 2 3 4 5 | update:function(packageUrl){ hmd.msg('===正在下载更新文件===', hmd.MSG_LEVEL.warnings); hmd.updater.get(packageUrl + '?' + new Date() * 1) .then(function (data) { fs.writeFileSync(updatePath + '\\update.zip',data.buffer); hmd.updater.install(); }); }, |
install将补丁包通过
7z.exe解压覆盖到程序目录,然后提示用户重启软件.
1 2 3 4 5 | install: function () { //移动配置文件 require("child_process").exec('xcopy "' + updatePath + '\\package.json" "' + execPath + '\\package.json" /s /e /y'); //解压缩补丁文件 var unzip = execPath + '\\7z.exe x '+ updatePath +'\\update.zip -y'; require("child_process").exec(unzip,function(){ hmd.msg('===更新完成,重启后生效==='); }); } |
绑定更新按钮
更新模块完成了,现在将功能绑定到按钮上.先在modules/directives增加新的directive
hmdUpdate
1 2 3 4 5 | angular.module('hmd.directives', []) .directive('hmdUpdate', [function () { return function (scope, elem) { $(elem[0]).on('click', function () { hmd.updater.checkUpdate(); }); }; }]) |
1 | <a class="btn rectbtn" href="javascript://" title="点击检查更新" hmd-update>...</a> |
updater.js
1 2 3 | <script src="modules/app.js"></script> <script src="modules/updater.js"></script> <script src="modules/directives.js"></script> |
总结
基本的自动更新的功能比图片上传更为简单,但是今天做的这个功能还有很多细节问题,比如:无法自动删除新版本不需要的文件
以后如果程序大了,更新补丁每次都全量打包会导致更新很慢
更新后不会自动重启软件.
更好的方案是自动根据git的提交信息生成更新列表,并且根据版本号管理.
接下来的计划:
云同步.
插件机制
表情插件.
附件
本篇程序打包.项目地址
相关文章推荐
- 自己动手开发更好用的markdown编辑器-04(实时预览)
- 自己动手开发更好用的markdown编辑器-05(粘贴上传图片)
- 自己动手开发更好用的markdown编辑器-07(扩展语法)
- 自己动手制作更好用的markdown编辑器-01
- 自己动手制作更好用的markdown编辑器-02
- 自己动手制作更好用的markdown编辑器-03
- 自己动手弄基于QT5和directx11的简单粒子编辑器v0.1(一个编辑器,一个更新器,一个linux服务端程序)
- 自己动手设计代码编辑器——(四)代码智能提示(自动完成功能)
- 动手开发自己的mvc-2----完善控制层,提供自动注入和注解上传等功能
- 自己动手开发jQuery插件全面解析 jquery插件开发方法(这个写的还可以,但不够细致)
- 自己动手开发jQuery插件
- angular+ionic+cordova(实战项目开发中,持续更新自己学到的和遇到的)
- .NET开发阵营由于微软的某种原因,已经失去了创新的动力,几乎所有的人都在等待着,等待着微软给出更新的,更好的工具。
- 【持续更新】.Net 开发中给自己埋下的坑!
- 自己动手打造基于 WKWebView 的混合开发框架(一)WKWebView 上手
- 自己动手搭建React开发环境之五Conclusion
- MVC开发Markdown编辑器(2)
- 自己动手,开发基于工作流的全生命周期配置管理系统
- 自己动手打造嵌入式Linux软硬件开发环境