摘要:本篇文章主要介绍腾讯团队从到在工程化的思考和实践。的全称是前端工作流,致力于提升研发效率和规范的工程化解决方案。最后腾讯团队的工程化解决方案已经开源主页如果对您的团队或者项目有帮助,请给个支持一下哈
本篇文章主要介绍腾讯IVWEB团队从0到1在工程化的思考和实践。feflow的全称是Front-end flow(前端工作流),致力于提升研发效率和规范的工程化解决方案。愿景是通过feflow,可以使项目创建、开发、构建、规范检查到最终项目上线的整个过程更加自动化和标准化。
要解决的问题项目的目录结构按约定生成
团队有一套开发规范进行约束
支持多种类型的构建,包括Fis构建和webpack构建
团队内部的代码贡献统计、离线包内置App等
为了解决上述问题,我们于17年2月底开始投入工程化feflow工具的开发和相关规范的制定,目前已经研发出了 feflow 的 CLI 版本,后续会推出 GUI 版本。
架构设计为了让 feflow 的具有高可扩展性,我们设计了4层结构,分别是:插件生态、内核层、参数解析器和控制台。除了贯穿整个开发工作流的基础命令选择通过内部插件内置在CLI 的Core里面,其它非必要命令统一通过插件机制进行扩展。
另一方面,为了使得 feflow 能够适用多种类型的项目。我们开发了多种类型的业务脚手架,如:活动模板、App H5模板、RN模板和业务组件模板。
执行过程当用户在控制台里面输入某个命令。首先会通过CLI 的参数解析器,将这个命令解析成一个object对象,然后传递给CLI 的内核。所有的命令都是通过内核上下文提供的 register 函数 进行注册的,一方面内核自身会读取内置插件 注册的基础命令,另一方面,内核会读取本地已经安装的外部插件注册的命令。如果找到用户输入的命令则开始执行命令对应的回调函数。
基础命令设计# 初始化项目 $ feflow init # 本地开发 $ feflow dev # 代码质量检查 $ feflow lint # 打包构建 $ feflow build # 代码发布 $ feflow publish # 安装插件、脚手架等 $ feflow install package # 配置本地客户端,如: npm 的源和 proxy $ feflow config
前面提到,CLI 的命令包含两部分,分别是内置在内核里的基础命令和外部插件提供的命令。那么外部插件要如何设计呢?
插件机制设计 插件实现原理这里有一个非常巧妙的设计,通过使用node提供的module和vm模块,可以通注入feflow全局变量来访问到cli的实例。从而能够访问cli上的各种属性,比如config, log和一些helper等。
loadPlugin(path, callback) { const self = this; return fs.readFile(path).then((script) => { const module = new Module(path); module.filename = path; module.paths = Module._nodeModulePaths(path); function require(path) { return module.require(path); } require.resolve = function(request) { return Module._resolveFilename(request, module); }; require.main = process.mainModule; require.extensions = Module._extensions; require.cache = Module._cache; // Inject feflow variable script = "(function(exports, require, module, __filename, __dirname, feflow){" + script + "});"; const fn = vm.runInThisContext(script, path); return fn(module.exports, require, module, path, pathFn.dirname(path), self); }).asCallback(callback); }命令注册:
命令需要以feflow.cmd.register进行注册,比如:
feflow.cmd.register("deps", "Config ivweb dependencies", function(args) { console.log(args); // Plugin logic here. });
说明:
register有3个参数,第一个是子命令名称,第二个是命令描述说明信息,第三个是对应的子命令执行逻辑函数。
feflow会将命令行参数args解析成Object对象,传递给插件处理函数
配置可以通过feflow.version获取当前feflow的版本,feflow.baseDir 获取feflow跟目录(在用户目录下的.feflow),通过feflow.pluginDir 获取插件目录
日志通过feflow.log来进行相关命令行日志输出
const log = feflow.log; log.info() // 提示日志,控制台中显示绿色 log.debug() // 调试日志, 命令行增加--debug可以开启,控制台中显示灰色 log.warn() // 警告日志,控制台中显示黄色背景 log.error() // 错误日志,控制台中显示红色 log.fatal() // 致命错误日志,,控制台中显示红色安装
插件开发完成后,可以通过 feflow 提供的 install 命令安装插件。安装的插件会放置在本地客户端 ~/.feflow/node_modules 文件夹下,并且写入到 ~/.feflow/package.json 中
$ feflow install feflow-plugin-xxx // 安装某个插件
之后每次运行命令时,便会从本地加载插件所注册的命令
全量更新和增量更新当CLI发布了一个新的版本,可能我们会废弃掉某些功能或者提供了新功能。这个时候如果用户依然使用的是旧版本,由于某些服务已经废弃掉了则会报错。在这种新旧版本不兼容的情况下,如何强制用户进行CLI的升级呢?需要在运行命令之前检查本地的CLI是否和远程提供的新版本是否兼容。在新旧版本不兼容时,会强制全量更新。如何判断当前用户安装的本地版本和远程最新版本是否兼容呢?
这里非常巧妙的运用了一下 npm 的 registry机制,每次发布新版本,我们会在 package.json 里面新增一个自定义字段 compatibleVersion,它的值是一个 semver 的版本号。本地检查时,会读取本地已经安装的版本和远程最新的版本进行比较,看看是否满足 compatibleVersion 的要求。如果不满足,则会自动运行 npm install feflow-cli 到最新的版本。
"configs": { "compatibleVersion": ">=0.13.0" },
对于插件,采取的是增量更新机制。每个发布到 npm 上的插件的package.json 中同样会有上面的这个字段,对于本地安装的不兼容的插件列表,会采取增量更新。
多类型脚手架的架构设计项目拷贝存在的问题显而易见,大致有以下三个方面:
容易出错;一旦某个关键文件拷贝丢失或者错误,很可能需要耗费半天到一天的时间排查环境问题。
不同场景下对目录结构要求不同;平时开发过程中,工程通常会分为运营活动、Hybrid业务、入口级别的项目(对性能和体验有极致和苛刻的要求)。需要基于RN或者Node.js的首屏直出,还有常用的业务组件等的开发。
新的Feature和BugFix难以同步;某个同学开发过程中增加的新方法或者解决的bug很难传递给其它同学并且沉淀成经验积累下来。
社区里面提供了完美的Yeoman解决方案,它是为了自动化项目的创建而生。Yeoman创建项目包括以下几个阶段:
initializing: 初始化一些状态之类的,通常是和用户输入的 options 或者 arguments 打交道
prompting: 和用户交互的时候(命令行问答之类的)调用
configuring: 保存配置文件(如 .babelrc 等)
writing: 生成模板文件
install: 安装依赖
end: 结束部分,初始代码自动提交
我们只需要继承Yeoman的Generator类做模板定制化,基于Yeoman的脚手架设计思路应该如下图所示:
当开发者输入 feflow init 命令时,开发者会告诉CLI需要创建哪一种类型的项目,CLI收到命令后。从本地已经安装的Yeoman脚手架里面选择某种类型的模板。然后,CLI会调用Gitlab API在远程创建仓库并且授予开发者master权限。接下来,会根据实际业务场景需要,自动化申请一些打点信息,常见的如离线包id,监控告警id等等。之后,在本地目录生成代码并且安装项目依赖的npm包,最后将本次初始化生成的所有代码自动提交到远程Git仓库。
多类型主流构建支持为了让feflow 支持多种类型的构建环境,比如 Fis3 和 webpack,或者前不久刚推出的号称零配置成本的 Parcel 构建。在每个项目的跟目录会放置一份配置文件,名称为 feflow.json。它的配置可能是这样的:
{ "builderType": "builder-webpack3", "builderOptions": { "moduleName": "mobile", "bizName": "category", "minifyHTML": true, "minifyCSS": true, "minifyJS": true, "usePx2rem": true, "remUnit": 100, "remPrecision": 8, "inject": true, "port": 8001 } }
builderType为构建的npm包,builderOptions为构建的参数配置。
最后腾讯IVWEB团队的工程化解决方案feflow已经开源:Github主页:https://github.com/feflow/feflow
如果对您的团队或者项目有帮助,请给个Star支持一下哈~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/107614.html
摘要:之后,在本地目录生成代码并且安装项目依赖的包,最后将本次初始化生成的所有代码自动提交到远程仓库。按照城市评选,分别评选明日之子仅限男性参加和闪亮女神仅限女性参加。 背景: 随着开发团队规模不断发展壮大,在人员增加的同时也带来了协作成本的增加,业务项目越来越多,类型也各不相同。常见的类型有组件类、活动类、基于React+redux的业务项目、RN项目、Node.js项目等等。如果想要对每...
摘要:当下最流行的模块打包器于年月日正式发布版本,代号。从官方的发布日志来看本次大版本更新带来了很多新特性更新和改善,这将会让的配置更加简单。本文,笔者将会全面介绍的新特性及实践。只支持模块,目前处于试验阶段。 导语: webpack是一个JS应用打包器, 它将应用中的各个模块打成一个或者多个bundle文件。借助loaders和plugins,它可以改变、压缩和优化各种各样的文件。它的输入...
摘要:的编译构建上一篇文章详解中介绍了基于事件流编程,是个高度的插件集合,整体介绍了的编译流程。本文将单独聊一聊最核心的部分,编译构建。的编译重要的构建节点的构建中总会经历如下几个事件节点。 webpack的编译&构建 上一篇文章webpack详解中介绍了webpack基于事件流编程,是个高度的插件集合,整体介绍了webpack 的编译流程。本文将单独聊一聊最核心的部分,编译&构建。 web...
摘要:其中负载均衡那一节,基本上是参考的权威指南负载均衡的内容。开发指南读了一半,就是看这本书理解了的事件循环。哈哈创京东一本骗钱的书。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯IVWEB团队 发表于云+社区专栏作者:link 2014年一月以来,自己接触web前端开发已经两年多了,记录一下自己前端学习路上看过的,以及道听途说的一些书,基本上按照由浅入深来介绍...
摘要:其中负载均衡那一节,基本上是参考的权威指南负载均衡的内容。开发指南读了一半,就是看这本书理解了的事件循环。哈哈创京东一本骗钱的书。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯IVWEB团队 发表于云+社区专栏作者:link 2014年一月以来,自己接触web前端开发已经两年多了,记录一下自己前端学习路上看过的,以及道听途说的一些书,基本上按照由浅入深来介绍...
阅读 3177·2021-09-06 15:02
阅读 2225·2019-08-30 15:48
阅读 3422·2019-08-29 11:08
阅读 3263·2019-08-26 13:55
阅读 2423·2019-08-26 13:35
阅读 3137·2019-08-26 12:11
阅读 2581·2019-08-26 11:48
阅读 858·2019-08-26 11:42