基于NodeJS从零构建线上自动化打包工作流(H5-Dooring特别版)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: NodeJS在前端领域正扮演着越越重要的地位,它不仅可以让前端工作者使用javascript编写后端代码,还能方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动,**非阻塞I/O **模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。

网络异常,图片无法展示
|


前言


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


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


你将收获


  • 设计一款在线工作流的基本思路
  • nodejs常用API的使用
  • nodejs如何使用父子进程
  • 使用child_processexec实现解析并执行命令行指令
  • 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.jsfunctioncomputedTotal(arr, cb) {
// 耗时计算任务}
// 与主进程通信// 监听主进程信号process.on('message', (msg) => {
computedTotal(bigDataArr, (flag) => {
// 向主进程发送完成信号process.send(flag);
  })
});
// main.jsconst { fork } =require('child_process');
app.use(async (ctx, next) => {
if(ctx.url==='/fetch') {
constdata=ctx.request.body;
// 通知子进程开始执行任务,并传入数据constres=awaitcreatePromisefork('./child.js', data)
  }
// 创建异步线程functioncreatePromisefork(childUrl, data) {
// 加载子进程constres=fork(childUrl)
// 通知子进程开始workdata&&res.send(data)
returnnewPromise(reslove=> {
res.on('message', f=> {
reslove(f)
        })
    })  
  }
awaitnext()
})

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'constoutWorkDir=resolve(__dirname, '../h5_landing')
constfid=uuid(8, 16)
constcmdStr=`cd ${outWorkDir}&& yarn build ${fid}`// ...exec相关代码constfilePath=resolve(__dirname, '../h5_landing/src/assets/config.json')
constres=WF(filePath, data)
exec(cmdStr, function(err,stdout,stderr){
if(err) {
// 错误处理  } else {
// 成功处理  }
})

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


4. socket.io实现消息实时推送



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


  • 客户端请求长轮询
  • postmessage消息推送
  • websocket双向通信


很明显使用websocket双向通信会更适合本项目。这里我们直接使用社区比较火的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 })
  }
})
// 浏览器端constsocket=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



目录
相关文章
|
17天前
|
运维 监控 安全
构建高效运维体系:从监控到自动化的全方位实践
本文深入探讨了构建高效运维体系的关键要素,从监控、日志管理、自动化工具、容器化与微服务架构、持续集成与持续部署(CI/CD)、虚拟化与云计算以及安全与合规等方面进行了全面阐述。通过引入先进的技术和方法,结合实际案例和项目经验,为读者提供了一套完整的运维解决方案,旨在帮助企业提升运维效率,降低运营成本,确保业务稳定运行。
|
16天前
|
机器学习/深度学习 运维 Prometheus
构建高效运维体系:从自动化部署到智能监控的全方位实践
在当今数字化时代,企业对运维效率和稳定性的要求越来越高。本文将探讨如何构建一个高效的运维体系,从自动化部署、持续集成与持续交付(CI/CD)、智能监控、故障管理以及数据驱动决策等方面进行深入分析和实践指导。通过这些方法,企业可以实现更快速、更可靠的软件发布和问题解决,提升整体运营效率。
|
11天前
|
敏捷开发 运维 Prometheus
构建高效运维体系:从基础架构到自动化管理
本文探讨了如何通过优化基础架构、引入自动化工具和流程,以及加强团队协作,构建高效的运维体系。通过案例分析和实践建议,帮助运维人员实现系统的稳定性、可靠性和可维护性。
|
6天前
|
机器学习/深度学习 运维 Cloud Native
构建高效运维体系:从自动化到智能化的演进之路
在当今数字化时代,运维作为信息技术的重要支柱,其效率与创新能力直接关系到企业信息系统的稳定性和业务连续性。本文将探讨如何通过技术手段,实现运维从传统手工操作向自动化、智能化的转变,进而构建一个高效、可靠的运维体系。我们将从自动化工具的应用开始,逐步深入到智能运维的实践,最终展望云原生架构下的运维未来趋势。
|
7天前
|
Web App开发 JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的深度整合
【9月更文挑战第28天】在现代Web开发领域,Node.js和Express框架的结合已成为打造高性能、易扩展应用的黄金组合。本文将深入探讨如何利用这一技术栈优化Web应用架构,提供具体实践指导,并分析其性能提升的内在机制。通过代码示例,我们将展示从基础搭建到高级功能的实现过程,旨在为开发者提供一条清晰的学习路径,以实现技术升级和项目效率的双重提升。
20 3
|
9天前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进之路
在当今数字化时代,运维作为保障企业IT系统稳定运行的关键环节,正经历着前所未有的变革。本文将探讨如何通过实施自动化和引入智能化技术,构建一个更加高效、可靠的运维体系,以应对日益复杂的业务需求和技术挑战。
21 1
|
16天前
|
缓存 监控 JavaScript
构建高效后端服务:Node.js与Express框架的完美结合
【9月更文挑战第18天】在数字化时代的浪潮中,后端服务的效率和稳定性成为了企业竞争力的关键。本文将深入探讨如何使用Node.js和Express框架来构建一个既高效又稳定的后端服务,同时通过实际代码示例,展示如何优化性能并确保服务的高可用性。
|
17天前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进之旅
在当今数字化时代,运维作为信息技术领域的核心组成部分,其重要性日益凸显。随着企业业务的不断扩展和技术的日新月异,传统手工运维方式已难以满足现代IT架构的需求。因此,构建一个高效、智能的运维体系成为业界共识。本文将探讨如何通过自动化和智能化手段,实现运维效率的质的飞跃,并分享一些成功案例与实践经验。
|
2天前
|
运维 监控 安全
构建高效运维体系:从监控到自动化的实践之路
在当今信息技术飞速发展的时代,运维作为保障企业信息系统稳定运行的关键环节,其重要性日益凸显。本文将探讨如何通过构建高效的运维体系,实现从被动响应到主动预防的转变,以及如何利用自动化工具提升运维效率和质量。我们将从运维的基本概念出发,逐步深入到监控、自动化和安全管理等方面,为企业提供一套实用的运维优化方案。
6 0
|
6天前
|
JSON JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的完美结合
【9月更文挑战第28天】在现代Web开发中,Node.js和Express框架的结合为创建高性能、易扩展的应用提供了强有力的支持。本文将深入探讨如何利用这两种技术构建一个简单但功能强大的Web服务,同时提供代码示例以加深理解。
下一篇
无影云桌面