腾讯IVWEB前端工程化工具feflow思考与实践

本篇文章主要介绍腾讯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 <key> <value>

前面提到,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.cnblogs.com/cpselvis/p/8467206.html

时间: 2024-11-09 00:14:36

腾讯IVWEB前端工程化工具feflow思考与实践的相关文章

前端工程化的个人思考

在我的印象中,一提到软件工程,首先不会想到的是前端这一块,大概是因为以往工作偏向的缘故.这两年最大的感触就是前端发展的很快,时下的前端开发也远非从网络中抠一段jQuery代码就能搞定功能这么简单. AJAX的出现第一次将前端的请求异步化,局部刷新使用户体验提升了一大截.NodeJS的出现则将前端的发展推向了高潮,一大批基于V8引擎.基于NodeJS之上的开发工具脱颖而出,极速的提升前端开发的效率.效果. 下面从几个方面,来梳理下近阶段关于前端的一些思考,仅供参考,欢迎在留言区讨论. 前端工程师岗

前端工程化工具Fekit分析

fekit 源码分析 从日常使用的命令分析fekit的工作方式 fekit 目录文件分析 fekit bin目录 fekit fekit命令入口,如果不带参数那么执行help显示帮助,否则执行对应的命令 fekit lib目录 cli 寻找命令,加载命令,初始化命令参数,显示命令帮助,执行命令.每个命令需要set_options,showHelp,usage,run框架方法约束 env 用户登陆鉴权,命令列表(基本和扩展),url的拼接,.fekitrc的操作 package fekit包管理工

前端开发工具vue.js开发实践总结

最近有很长时间没有更新博客了,换了公司,全部的心思都放在项目上了.通过这次项目的上线,让我感受最深的是前后端分离后,前端页面的模块化管理,以及前端页面的数据邦定.在接触vue.js之前,我之前端要用到的dom结构,都是通过拼接字符串的方式进行输出的.这种方式最大的痛点是拼接很麻烦,也不是很直观,几乎无法复用,和数据紧密的偶合在一起,维护不方便,太多太多的问题.在同事的推荐下,开始接触vue.js这个开源项目.如果你不知道什么是vue,那么请看这里的介绍http://vuejs.org/. vue

前端工程化,你做了多少?

前端工程化是近几年比较热门的一个东西,大大小小的团队也在朝着这一方向发展,那么你的团队做了多少呢? 前端发展简史 石期时代 最初的前端页面都是一些静态页面,人们看到的网页就像报纸一样. 青铜时代 后端为主的时代,往往页面都是后端利用一些模版引擎来完成页面:对于有大量页面的项目,前端在写页面需要构造一定的环境,比如jsp,php等. 铁器时代 随着ajax的诞生,浏览器可以主动从服务端拉取数据,前后端分离的时代到来,SPA应运而生,前端可以处理一些复杂的交互.业务逻辑. 工业时代 随着前端扮演的角

前端优化带来的思考,浅谈前端工程化

重复优化的思考 这段时间对项目做了一次整体的优化,全站有了20%左右的提升(本来载入速度已经1.2S左右了,优化度很低),算一算已经做了四轮的全站性能优化了,回顾几次的优化手段,基本上几个字就能说清楚: 传输层面:减少请求数,降低请求量执行层面:减少重绘&回流 传输层面的从来都是优化的核心点,而这个层面的优化要对浏览器有一个基本的认识,比如: ① 网页自上而下的解析渲染,边解析边渲染,页面内CSS文件会阻塞渲染,异步CSS文件会导致回流 ② 浏览器在document下载结束会检测静态资源,新开线

关于测试工具以及前端性能测试的一些思考

对于下一代测试工具的思考. 在以往的性能测试工作中,一直以来使用的测试工具框架都是基于请求-响应模型来进行开发的, 该模型是指脚本通过模拟HTTP请求并接收服务器的响应来针对被测对象的响应时间等考评指标来进行考评. 目前主流的性能测试工具都产生于瘦客户端的时代,而且由于基于的HTTP请求-响应模型本身是很标准的模型, 因此工具更容易做到普适性. 但是很多时候我们测试的结果看着很漂亮,但是实际用户在使用的时候却感觉系统性能糟透了, 抛开场景本身在抽象后与实际场景的差异,这种测试时间和体验时间之间的

前端工程化系列[03]-Grunt构建工具的运转机制

在前端工程化系列[02]-Grunt构建工具的基本使用这篇文章中,已经对Grunt做了简单的介绍,此外,我们还知道了该如何来安装Grunt环境,以及使用一些常见的插件了,这篇文章主要介绍Grunt的核心组件和运转机制. Grunt是一套前端自动化构建工具,可以帮助我们简化开发中需要反复处理的任务,甚至可以实现自动构建等功能. Grunt拥有数量庞大的插件,这些插件能够帮助我们处理开发中遇到的绝大多数构建任务,比如代码的预编译.压缩.代码检查.单元测试等.但为什么在终端输入Grunt相关命令,就能

论前端工程化

在不知道什么时候,突然有人提起前端工程化这东西,一开始觉得又是某个大神故意提起的高深词汇,专门来吓唬人的. 继而我疯狂查找了很多的资料,在接近二十篇的相关资料,每一篇文章都写得神乎其神,大有唯我独尊的意味,但每篇看下来,总感觉不对经--就是大家都把自己一套比较规范的开发套路充当出前端工程化,前端工程化变成了前端优化,让人看了,"对啊,这样做规范多了,优化不错啊,巴拉巴拉",但又觉得工程化不应该只是这些,像缺什么,让人看得云里雾里,似懂非懂.这种文章虽不算误人子弟,但讳莫如深,妖魔化了前

前端工程化(摘抄)

目前来说,Web业务日益复杂化和多元化,前端开发已经由以WebPage模式为主转变为以WebApp模式为主了.现在随便找个前端项目,都已经不是过去的拼个页面+搞几个jQuery插件就能完成的了.工程复杂了就会产生许多问题,比如:如何进行高效的多人协作?如何保证项目的可维护性?如何提高项目的开发质量?... 前端工程化是前端架构中重要的一环,就是为了解决上述各种效率方面的问题的.而前端工程本质上是软件工程的一种,因此我们应该从软件工程的角度来研究前端工程. 那么前端工程化需要考虑哪些因素?我认为前