背景: 随着开发团队规模不断发展壮大,在人员增长的同时也带来了协做成本的增长,业务项目愈来愈多,类型也各不相同。常见的类型有组件类、活动类、基于React+redux的业务项目、RN项目、Node.js项目等等。若是想要对每一个项目进行一些规范的约束好比Git提交规范、Javascript规范简直难于登天。全部的这些,只由于缺乏一个好用的工程化工具。从项目建立、开发、构建、代码规范检查到最终项目上线,经过CLI能够提高效率,同时保障开发规范的实施。javascript
关键点在于package.json里面的bin字段。模块全局安装,对于类unix系统,在/usr/local/bin目录建立软连接;对于windows系统,在C:\Users\username\AppData\Roaming\npm目录建立软连接。
模块局部安装,会在项目内的./node_modules/.bin目录建立软连接。前端
随着前端工程的不断演进,一方面工程变得日趋复杂,同时对规范和质量的诉求在不断增长。现代化web工程应该包含如下几个阶段:初始化、开发、构建、检查、发布。以下图所示:java
项目拷贝存在的问题显而易见,大体有如下三个方面:node
社区里面提供了完美的Yeoman解决方案,它是为了自动化项目的建立而生。Yeoman建立项目包括如下几个阶段:react
咱们只须要继承Yeoman的Generator类作模板定制化,基于Yeoman的脚手架设计思路应该以下图所示:git
首先,开发者会和CLI进行交互,开发者会告诉CLI须要建立哪种类型的项目,CLI收到命令后。从本地已经安装的Yeoman脚手架里面选择某种类型的模板。而后,CLI会调用Gitlab API在远程建立仓库而且授予开发者master权限。接下来,会根据实际业务场景须要,自动化申请一些打点信息,常见的如离线包id,监控告警id等等。以后,在本地目录生成代码而且安装项目依赖的npm包,最后将本次初始化生成的全部代码自动提交到远程Git仓库。github
基于React+redux组件化开发方式中,一个页面或者webapp是由多个容器组件拼装后渲染而成。web
某个组件一般是由:模板、cgi数据和事件组成。理想状况下,开发和产品和平共处,你能够把一个组件写成下面这个样子,好比规则组件:npm
render() { return ( <div className="lottery-rule"> <div className="section"> <h3>活动时间:</h3> <p>9月14日~9月30日</p> </div> <div className="section"> <h3>活动规则:</h3> <p>一、活动期间,在NOW app上录制小视频,上传成功后便可参赛。</p> <p>二、根据参赛小视频得到的点赞数进行排行。</p> <p>三、按照城市评选,分别评选“明日之子”(仅限男性参加)和”闪亮女神“仅限女性参加。</p> </div> </div> ); }
咋一看,上面的写法没什么问题。实际确极可能是七、8次的文案修改,甚至对外入口开放后仍然要修改文案或者图片等静态数据。而后,你须要走代码发布流程。json
更好的解决思路是:在开发某个业务组件以前,结合以往的经验,分析哪些静态数据极可能是须要高频次的修改。将这些高频次修改的静态数据抽离出来,对于万年不变的数据则没有必要抽出来。那么,如何将静态数据动态化呢?
答案是: Schema First , 开发组件以前先设计Schema,经过schema生成一个form表单,达到静态数据和模板分离。若是使用React开发,能够基于react-jsonschema-form定制。静态数据和模板分离以后应该以下图:
此处以Git commit规范为例子进行相关改进介绍。
良好的Git commit规范有如下优点:
此处采用Google angular项目的提交做为参考,整理出Git commit的解决方案:
具体的提交格式要求以下:
<type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer>
对格式的说明以下:
一键生成Changelog版本日志:
一次血淋淋的生产环境事故:2017年4月13日,腾讯高级工程师小圣在作充值业务时,修改了苹果iap支付配置,将JSON配置增长了重复的key。代码发布后,有小部分使用了vivo手机的用户反馈充值页面白屏,没法在Now app内进行充值。最后问题定位是:vivo手机使用了系统自带的webview而没有使用X5内核,解析JSON时遇到重复key报错,致使页面白屏。
分析:现代化的浏览器对于JSON里面的重复key会作兼容处理,可是某些老旧的浏览器内核并不会,好比此处的vivo手机,致使代码直接出错。那么,如何避免相似问题再次出现呢?
此处不得不说起ESLint,ESLint于2013年6月推出最新版本v4.6.0,是一款适用于Javascript和JSX的代码规范检查工具,相比JSLint和JSHint而言,它更加灵活,支持自定义配置、插件扩展和配置错误级别。虽然接入ESLint会给团队的同窗增长很多代码修改的成本,可是从长远来看,收益确定是大于付出的。
Javascript规范制定的原则:
为了更好的定制和维护Javascript规范,咱们建立了eslint的shareable config。一方面,咱们以为eslint:recommend 里面的部分配置定义的错误级别过于严格,好比代码里面出现了console会致使校验错误,另外一方面,它没有包含ESLint的最佳实践和其它规则。咱们定义的部分规则解释以下:
规则名称 | 错误级别 | 说明 |
---|---|---|
for-direction | error | for 循环的方向要求必须正确 |
getter-return | error | getter必须有返回值,而且禁止返回值为undefined, 好比 return; |
no-await-in-loop | off | 容许在循环里面使用await |
no-console | off | 容许在代码里面使用console |
no-prototype-builtins | warn | 直接调用对象原型链上的方法 |
valid-jsdoc | off | 函数注释必定要遵照jsdoc规则 |
no-template-curly-in-string | warn | 在字符串里面出现{和}进行警告 |
accessor-pairs | warn | getter和setter没有成对出现时给出警告 |
array-callback-return | error | 对于数据相关操做函数好比reduce, map, filter等,callback必须有return |
block-scoped-var | error | 把var关键字当作块级做用域,防止变量提高致使的bug |
class-methods-use-this | error | 要求在Class里面合理使用this,若是某个方法没有使用this,则应该申明为静态方法 |
complexity | off | 关闭代码复杂度限制 |
default-case | error | switch case语句里面必定须要default分支 |
ESLint的执行能够接入到PUSH hook里面,步骤以下:
#1, 安装husky $ npm install husky --save-dev #2, 集成进npm script { "scripts": { "precommit": "validate-commit-msg", "prepush": "eslint src ./.eslintrc.js --ext '.js,.jsx'" } }
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. });
说明:
能够经过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() // 致命错误日志,,控制台中显示红色
感谢OSC源创汇提供的交流机会,能和广大开发者分享和交流学习,CLI源代码托管在Github和码云上:
附件:本次分享PPT