概述
Command Line Interface,简称cli,是一种通过命令行来交互的工具,旨在减少低级重复劳动,专注业务提高开发效率。在前端三大框架里,angular、vue、react都有各自cli的官方实现。虽然官方的cli能提高我们开发的效率,但具体到公司的业务时,官方的cli就提供不了多大的忙了。若平时的工作内容要经常复制粘贴代码再进行开发的话,那么自定义一个cli就很有必要了。
下文将会把angualr-cli的核心功能抽离出来制作自己的cli模板并用于非angular的前端项目中。
angular的原理图
"Angular是一个应用设计框架与开发平台,用于创建高效、复杂、精致的单页面应用。"
这句话是angular文档的第一句话,下面简单演示下angular-cli的创建项目、模块、组件功能
- 创建angular项目
- 创建组件
可以发现通过angular-cli创建的组件,不仅创建了组件本身,还在app模块里自动引入了刚创建的组件,不必手动引入。
- 创建模块
通过命令创建一个新的模块,并且以添加额外参数的方式创建一个新的组件,发现新的组件创建出来是没有附带文件夹的,然后还自动注册在新的模块里而不是app模块。
- 小结
angular-cli内置的原理图可以使得ng开发者能快速的创建项目、模块、组件、服务、管道、指令等文件并自动注册到父级模块中,根据不同的参数还有不同的创建效果,开发者在创建模版后再进行开发。angular拥有如此方便的cli功能,下文将把angular-cli的核心功能@angular-devkit/schematics和@angular-devkit/schematics-cli抽离出来并实践于非angular的前端项目中。
入门
原理图概念
前端项目中的cli对于文件的创建基本都是基于node的fs文件系统。@angular-devkit/schematics会将真实文件抽象成虚拟文档树,我们将对虚拟文档树进行文件的增删改查操作,最后虚拟文档树会合并到真实文件系统中,以此来对文件进行操作。
步骤
- 安装依赖
npm install @angular-devkit/schematics-cli -g
- 创建原理图
schematics blank mySchematic1
输入命令后将会生成一个原理图,schematics会自动检测原理图是否处于原理图集合中,如果不是则会自动生成一个原理图集合项目并安装依赖,否则将生成原理图本身并自动更新原理图集合项目中的collection.json文件。
文件的增删改操作
-
前置步骤
经过上述操作目录结构如图
1.修改package.json里的build命令为
tsc -p tsconfig.json --watch,因为node执行的是ts编译后的js文件,添加--watch参数能监听文件的变化然后自动编译为js文件,省得每次修改完代码都要自己编译一遍。
2.修改tsconfig.json里的配置项noUnusedParameters:false和noUnusedLocals:false,ts文件校验不成功就编译不了,修改配置项适当宽松下校验规则。
3.在原理图集合项目运行命令npm run build和npm link,此时该项目已经处于监听状态和被映射到全局node_modules中了。 -
创建文件
为mySchematic1中的index.ts文件添加一行代码如图
接下来运行命令
schematics my-schematic1:my-schematic1便会在命令同级目录生成hello.txt文件
尝试更复杂点的创建文件,创建一个files文件夹并创建一个目录和css、js、html三个文件和修改index.ts文件如图
重新运行命令schematics my-schematic1:my-schematic1可以看到同级目录生成了刚刚编写的代码并且能直接打开html没任何问题
-
更改文件
更改文件的原理相当于修改字符串,原理虽然简单但实际操作起来是比较难的,angular-cli是用AST抽象语法树来进行修改的。这边针对js文件或html文件可以使用一个讨巧的方式来在指定位置插入代码以完成文件修改。在要修改代码的位置添加注释, 并修改index.ts文件的代码重新运行命令
schematics my-schematic1:my-schematic1看到js文件和html文件已被修改
-
删除文件
删除比较简单,修改index.ts文件,然后重新运行命令schematics my-schematic1:my-schematic1,结果如图
-
增加交互
接下来在my-schematic1原理图中添加schema.json文件,并修改collection.json,指向刚创建的schema.json,修改index.ts如图
schema.json代码
{
"$schema": "http://json-schema.org/schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"default":"Leemagination",
"description": "The name of the template."
},
"requiredKey":{
"type":"string"
},
"question":{
"type":"string",
"x-prompt":"请随便输入:"
},
"style": {
"type": "string",
"default": "touchFish",
"enum": ["work","touchFish","learn"],
"x-prompt": {
"message": "请问你今天打算干些什么呢?",
"type": "list",
"items": [
{ "value": "work", "label": "工作" },
{ "value": "touchFish", "label": "摸鱼" },
{ "value": "learn", "label": "学习" }
]
}
}
},
"required": [
"requiredKey"
]
}
接下来运行schematics my-schematic1:my-schematic1 --requiredKey=biubiuibu,输入文字和选择后结果如图
可以发现index.ts里的_options对象含有输入命令附带的参数,而schema.json则会规范参数的输入以及提供更多的交互能力。由于schema.json的required数组里有requiredKey,如果运行命令时不附带这个参数将会报错。
编写模版
除了编写静态的模板,这个模板还能使用ejs的部分语法
| 占位符 | 描述 |
|---|---|
| <%= expression %> | 替换为给定表达式的调用结果。它只支持直接表达式,不支持结构化(for/if/…)JavaScript。 |
| <%- expression %> | 与上面相同,但插入时HTML的结果值将被转义(即将“<”替换为“<”) |
| <% inline code %> | 将给定的代码插入到模板结构中,允许插入结构JavaScript。 |
| <%# text %> | 一段文本说明,生成模板时会被删除 |
在my-schematic2原理图添加config.ts文件,修改index.ts和collection.json文件如图
新建两个模板文件如图
collection.json添加了原理图的缩写名称,运行命令schematics my-schematic1:ms2将会把模板结合上config.ts的数据生成文件如图
ejs的语法模板文件若被IDE识别为错误语法,可以在模板文件添加上后缀.template,然后把index.ts里的template修改为applyTemplate,这样子生成文件会自动把.template后缀删掉。如图
应用
接下来演示自定义模版在vue项目中的使用。要达到的目的就是通过自定义的模版和配置项完成业务页面的创建并自动更新路由、页面显示和完成表单弹框的创建并在主页创建弹框按钮。上文的schematics是作为一个独立项目通过npm link的形式来使用,这里将schematics完全融合进前端项目里。
步骤
- 在vue项目中安装依赖
npm install @angular-devkit/core -D
npm install @angular-devkit/schematics -D
npm install @angular-devkit/schematics-cli -D
npm install patch-package -D
- 在vue项目中编写模板文件并添加一个针对schematics进行编译的tsconfig.json配置文件
- 修改node_modules中@angular-devkit/schematics-cli/bin/schematics.js的源代码
- 修改package.json文件如图
- 运行
npx patch-package @angular-devkit/shematics-cli生成patch文件,这样该项目每次npm install后的node_modules是修改后的文件。patch-package npm地址
创建页面演示
创建表单演示
Talk is cheap
小结
可以将重复劳动的事情抽象然后编写模板,输入指令后即可生成文件。如果逻辑比较复杂的也能在创建文件的基础上继续进行二次开发。schematcis可以是独立的项目通过npm link的形式或者发布npm包使用,也可以安装依赖并修改源码嵌入到前端项目中。
最后
有错误请指正