前言

NodeJS在前端领域正扮演着越越重要的地位,它不仅可以让前端工作者使用javascript编写后端代码,还能方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动,非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。

所以作为一名优秀的前端工程师,非常有必要了解和掌握Node.js。笔者接下来将通过对H5-Dooring项目中的实时在线下载代码功能来带大家掌握如何从零构建线上自动化打包工作流

你将收获

  • 设计一款在线工作流的基本思路
  • nodejs常用API的使用
  • nodejs如何使用父子进程
  • 使用child_processexec实现解析并执行命令行指令
  • http://socket.io实现消息实时推送
  • 使用jszip实现服务端压缩文件并支持前端下载zip

正文

我们都用过诸如gulpwebpack之类的自动化工具,他们能很方便的帮我们打包编译代码,并以一种相对优雅的方式编写我们的工程代码。但是我们仔细思考之后就能发现, 这些产物的背后都是靠nodejsbabel做底层支持。我们无非就是设计一种架构模式,通过babel的加载器和nodejs的服务能力,将代码由JS - AST - JS的过程(这里忽略css和插件处理)。

在吹完牛逼之后,我们开始介绍如何设计一款在线工作流

1. 设计一款在线工作流的基本思路

在线工作流是个泛指,其实任何产品线都有属于自己特色的工作流,但最终还是要回归业务。所以笔者在这里专门介绍一下H5-Dooring的实时下载代码的在线工作流。我们看看下面的设计流程:

以上就是我们需要做的在线实时打包下载代码的工作流,由于nodejs是单线程的,为了不阻塞进程我们可以采用父子进程通信的方式和异步模型来处理复杂耗时任务,为了通知用户任务的完成状况, 我们可以用socket做双向通信。在当前的场景下就是代码编译压缩完成之后,通知给浏览器,以便浏览器显示下载状态弹窗。一共有三种状态:进行中已完成失败。对应如下图所示界面:

至于为什么没有出现下载失败的状态,不要问我,问就是没有失败过(完了,找虐了)。

以上就是H5-Dooring实时编译下载的工作流设计,至于线上更多的实际需求,我们也可以参考以上设计去实现,接下来笔者来具体介绍实现过程。

2. nodejs如何使用父子进程

我们要想实现一个自动化工作流, 要考虑的一个关键问题就是任务的执行时机以及以何种方式执行. 因为用户下载代码之前需要等H5页面打包编译压缩完成之后才能下载, 而这个过程需要一定的时间(8-30s), 所以我们可以认定它为一个耗时任务.

当我们使用nodejs作为后台服务器时, 由于nodejs本身是单线程的,所以当用户请求传入nodejs时, nodejs不得不等待这个"耗时任务"完成才能进行其他请求的处理, 这样将会导致页面其他请求需要等待该任务执行结束才能继续进行, 所以为了更好的用户体验和流畅的响应,我们不得不考虑多进程处理. 好在nodejs设计支持子进程, 我们可以把耗时任务放入子进程中来处理,当子进程处理完成之后再通知主进程. 整个流程如下图所示:

nodejs有3种创建子进程的方式,这里笔者简单介绍一下fork的方式。使用方式如下:

// child.js
function computedTotal(arr, cb) {// 耗时计算任务
}// 与主进程通信
// 监听主进程信号
process.on('message', (msg) => {computedTotal(bigDataArr, (flag) => {// 向主进程发送完成信号process.send(flag);})
});// main.js
const { fork } = require('child_process');app.use(async (ctx, next) => {if(ctx.url === '/fetch') {const data = ctx.request.body;// 通知子进程开始执行任务,并传入数据const res = await createPromisefork('./child.js', data)}// 创建异步线程function createPromisefork(childUrl, data) {// 加载子进程const res = fork(childUrl)// 通知子进程开始workdata && res.send(data)return new Promise(reslove => {res.on('message', f => {reslove(f)})})  }await next()
})

在H5-Dooring线上打包的工作流中,我们会用到child_processexec方法,来解析并执行命令行指令。至于父子进程的更多应用,大家可以自行探索。

3. 使用child_processexec实现解析并执行命令行指令

在上面介绍的dooring工作流中,我们知道为了实现实时打包,我们需要一个H5 Template项目,作为打包的母版,当用户点击下载时,会将页面的json schema数据传给node服务器node服务器再将json schema进行数据清洗最后生成template.json文件并移动到H5 Template母版中,此时母版拿到数据源并进行打包编译,最后生成可执行文件。

以上的过程很关键, 这里笔者画个大致的流程图:

为了实现以上过程,我们需要两个关键环节: 1. 将用户配置的数据进行处理并生成json文件,然后移动到H5 Template母版中 2. 在母版中自动执行打包编译脚本

第一个环节很好实现,我们只需要用nodejsfs模块生成文件到指定目录即可,这里笔者重点介绍第二个环节的实现。

当我们将json数据生成到H5 Template中之后,就可以进行打包了,但是这个过程需要自动化的去处理,不能像我们之前启动项目一样,手动执行npm start或者yarn start。我们需要程序自动帮我们执行这个命令行指令,笔者在查nodejs API突然发现了child_processexec方法,可以用来解析指令,这个刚好能实现我们的需求,所以我们开始实现它。代码如下:

import { exec } from 'child_process'
const outWorkDir = resolve(__dirname, '../h5_landing')
const fid = uuid(8, 16)
const cmdStr = `cd ${outWorkDir} && yarn build ${fid}`// ...exec相关代码
const filePath = resolve(__dirname, '../h5_landing/src/assets/config.json')
const res = WF(filePath, data)exec(cmdStr, function(err,stdout,stderr){if(err) {// 错误处理} else {// 成功处理}
})

以上代码我们不难理解,我们只需要定义好打包的指令字符串(方式和命令行操作几乎一致),然后传入给exec的第一个参数,他就会帮我们解析字符串并执行对应的命令行指令。在执行完成之后,我们可以根据回调函数(第二个参数)里的参数值来判断执行结果。整个过程是异步的,所以我们不用担心阻塞问题,为了实时反馈进度,我们可以用socket来将进度信息推送到浏览器端。

4. http://socket.io实现消息实时推送

在上面介绍的 exec实现解析并执行命令行指令 中还有一些细节可以优化,比如代码执行进程的反馈,执行状态的反馈。因为我们用的是异步编程,所以请求不会一直等待,如果不采取任何优化措施,用户是不可能知道何时代码打包编译完成, 也不知道代码是否编译失败,所以这个时候会采取几种常用的放案: 客户端请求长轮询 postmessage消息推送 * websocket双向通信

很明显使用websocket双向通信会更适合本项目。这里我们直接使用社区比较火的http://socket.io.由于官网上有很多使用介绍,这里笔者就不一一说明了。我们直接看业务里的代码使用:

// node端
exec(cmdStr, function(err,stdout,stderr){if(err) {console.log('api error:'+stderr);io.emit('htmlFail', { result: 'error', message: stderr })} else {io.emit('htmlSuccess', { result: dest, message: stderr })}
})// 浏览器端
const socket = io(serverUrl);
// ...省略其他业务代码
useEffect(() => {socket.on('connect', function(){console.log('connect')});socket.on('htmlFail', function(data){// ...});socket.on('disconnect', function(e){console.log('disconnect', e)});
}, [])

这样我们就能实现服务器任务流的状态实时反馈给浏览器端了。

5. 使用jszip实现服务端压缩文件并支持前端下载zip

实现前端下载功能其实也很简单,因为用户配置的H5项目包含了各种资源,比如css,js,html,image,所以为了提高下载性能和便捷性我们需要把整个网站打包,生成一个zip文件供用户下载。原理就是使用jszip将目录压缩,然后返回压缩后的路径给到前端,前端采用a标签进行下载。至于如何实现目录遍历压缩和遍历读取目录, 这里笔者就不说了,感兴趣的可以参考笔者其他的nodejs的文章。

6. 总结

以上教程笔者已经集成到H5-Dooring中,对于一些更复杂的交互功能,通过合理的设计也是可以实现的,大家可以自行探索研究。

github地址:H5在线编辑器H5-Dooring

最后

如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。

更多推荐

徐小夕:基于f2从零实现移动端可视化编辑器​zhuanlan.zhihu.com

徐小夕:基于React+Koa实现一个h5页面可视化编辑器-Dooring​zhuanlan.zhihu.com

徐小夕:深度剖析github star数15.1k的开源项目redux-thunk​zhuanlan.zhihu.com

徐小夕:Dooring可视化之从零实现动态表单设计器​zhuanlan.zhihu.com

打包node服务端_如何基于NodeJS从零构建线上自动化打包工作流?相关推荐

  1. 使用 pkg 打包 node服务端 项目

    前言 最近自己写了一个nodejs+mysql+express 的项目,想着如果项目部署的话还要再安装 node 环境什么的,肯定太麻烦,于是就想有没有像webpack 那样打包项目的插件,于是了解到 ...

  2. oracle11g服务器端下载,安装_oracle11G_客户端_服务端_链接_oracle

    在开始之前呢,有一些注细节需要注意,oracle11G_客户端_和_服务端, 分为两种   一种是  开发者使用    一种是  BDA  自己使用(同时也需要根据自己 PC 的系统来做_win7_与 ...

  3. 开发测试服务器配置信息,node服务端中台实现及开发测试生产环境配置

    本人node服务端新人一枚,网上找了不少资料,看了很多别人的配置信息,感觉都不是很合适,看的多了自己也明白配置的具体思路跟实现方式了,以下为我的实现方式.通过package.json里面的script ...

  4. 用pdfjs 在 node服务端将pdf转为图片

    原文链接: 用pdfjs 在 node服务端将pdf转为图片 上一篇: puppeteer pdf 转图片 [不建议使用] 下一篇: 用dom-to-image 截取B站弹幕 [做了一半] 需要使用c ...

  5. pkg之打包node服务

    如何将用Node搭建的服务,在没有外网的情况下简单部署?通过查找自己和实践,找到了适合的技术--pkg,能将服务打包成一个exe文件,方便部署,既能保证代码的安全性,又能让使用者一键操作. 一.通过查 ...

  6. 基于JAVA古惠农产品线上销售系统计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA古惠农产品线上销售系统计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA古惠农产品线上销售系统计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目架构:B/S ...

  7. web电商、商城pc端、商城、购物车、订单、线上支付、web商城、pc商城、登录注册、人工客服、收货地址、现金券、优惠券、礼品卡、团购订单、评价晒单、消息通知、电子产品商城、手机商城、电脑商城

    web电商.商城pc端.商城.购物车.订单.线上支付.web商城.pc商城.登录注册.人工客服.收货地址.现金券.优惠券.礼品卡.团购订单.评价晒单.消息通知.电子产品商城.手机商城.电脑商城 Axu ...

  8. 【java毕业设计】基于Spring Boot+mysql的线上教学平台系统设计与实现(程序源码)-线上教学平台

    基于Spring Boot+mysql的线上教学平台系统设计与实现(程序源码+毕业论文) 大家好,今天给大家介绍基于Spring Boot+mysql的线上教学平台系统设计与实现,本论文只截取部分文章 ...

  9. 基于 Vue 的学生社团线上管理平台开发与设计

    0 引言 近年来, 各高校为丰富学生的校园生活. 培养学生的个性, 社团与社团人数增加迅速, 需要处理的各类信息也层出不穷, 传统的管理方式已经不利于快捷地处理这些问题. 因此管理不便. 信息错综复杂 ...

最新文章

  1. [WS]使用Axis发布简单的Web服务
  2. linux poll in,Linux poll机制详细讲解
  3. 检测代码区校验和实现简易反调试
  4. 项目经理主要工作职责
  5. LiveWriter测试
  6. Redis有几种数据类型?文末领取面试资料
  7. javq接口_java 接口详解
  8. 对于根目录磁盘满的了问题
  9. 样条曲线、样条函数、python绘画样条曲线
  10. sql 语句,主键外键详解
  11. mysql校对集工具_mysql字符集和校对规则(Mysql校对集)
  12. 兵卒情缘酒新品上市发布会
  13. Algorithms and Data Structures I
  14. android 应用程序Activity管理类
  15. hive 分区表select全部数据_Hive中如何快速的复制一张分区表(包括数据)
  16. 从第三方企业邮箱迁移至Office 365(21V) Exchange Online
  17. 脑电产品-时间常数与截止频率相互换算
  18. uniapp最好用的二维码生成
  19. linux 网卡网口指示灯闪烁指令 centos 7
  20. 罗斯蒙特流量计选用的误区

热门文章

  1. Epx5 MSF基础应用 20154326杨茜
  2. Tomcat几种启动报错及解决办法
  3. [NOIP2013] 花匠
  4. H3C-WA2210升级
  5. mac上的命令行工具
  6. (转)Android中JNI编程的那些事儿
  7. jquery中的ajax 网络请求
  8. 思维-CF-739A
  9. C#。2.1 运算符
  10. HDU-1712-ACboy needs your help