工作中遇到这么一个场景
管理后台需要进行精确权限控制,比如页面,接口等等,需要在权限管理页面一个个手动添加页面以及各个页面使用的接口,甚至还有各个页面的按钮权限。这就导致一些问题
- 当前次开发新增很多页面以及接口时,手动添加是一件很麻烦的事情,还比较考验眼力,一不小心就配错了
- 环境迁移,测试环境,预发布环境,还有正式环境数据库都是隔离的,这就导致切换环境时需要重新配置,工作量巨大,费事费力
思考方案
实现一个命令行工具
- 提供一个配置模板
- 添加op时,执行初始化命令create-op -i,拷贝这个配置模板,更改成自己本次需要创建的内容
- 执行create-op -c env 实现不同环境下的op创建
创建op就具体业务具体分析了,无非就是根据配置,组装接口需要数据,然后依次手动调用接口即可,这里不做更多展开
实现
创建项目
npm init 初始化项目,-y或--yes,指定项目走默认配置
创建可执行脚本
创建一个bin文件夹,用来存放可执行命令对应的文件
创建可执行命令文件
#!/usr/bin/env node
#! /usr/bin/env node 首行shebang语句,指定使用node解释程序执行脚本。 在不同的操作系统中,node [命令行]的位置不同,因此使用 env node 找到路径并执行
注册命令行命令,这一步是很重要的
当我们创建好bin文件后,会发现我们此时是可以直接执行这个文件的
那我们每次需要执行这个脚本时都要找到这个脚本的位置,显然是不太方便的。那我们应该怎么做呢?创建软链 如下所示在package.json 中添加bin字段映射命令关键字与可执行文件
{
...
"bin": {
"create-op": "./bin/index.js"
},
...
}
然后使用npm link安装本地模块,你就可以在{prefix}文件夹下看到你的命令了,当然这是因为我们现在是在本地开发模式下使用的这个方法
真正的开发中我们都是通过 npm install -g 或者 npm install安装远程模块的。在通过npm install -g全局安装的时候,npm会symlink可执行文件到{prefix}文件夹(Windows系统),npm install本地安装时,npm会symlink可执行文件到./node_modules/.bin 文件夹
可以使用npm prefix -g查看你的prefix目录
到这一步你就可以在任意位置打开命令行窗口,然后使用自己的命令了
如果想要取消软链,使用npm unlink -g <指令>的方式,当然你也可以去prefix文件夹下手动删除文件
命令行参数处理
此时就需要处理用户输入了,用户输入的就是命令行参数
console.log(process.argv);
process为node进程中的全局变量,process.argv为一数组,数组内存储着命令行的各个部分,argv[0]为node的安装路径,argv[1]为主模块文件路径,剩下为子命令或参数。
看一个简单的例子
#!/usr/bin/env node
const pkg = require('../package.json');
const opt = process.argv[2];
switch (opt) {
case '-v':
console.log(pkg.version);
break;
}
开发中简单使用process.argv搭配switch使用确实可以解决不少问题,但是如果工具功能越来越丰富可能就会面临参数过多,顺序不固定,甚至不知道取第几个参数的问题也会出现
此时需要引入一个专门处理命令行参数的包了,这里以commander库为例
具体使用可以参考官网,这里举个例子
const pkg = require('../package.json')
const { program } = require('commander');
// const { creatOp, creatOpInit } = require('../tool/index')
program
.version(pkg.version)
.option('-i, --init', '初始化op文件')
.option('-c, --create <env>', '根据环境和op配置文件创建op')
.action(opts => {
// 约定初始化文件
if (opts.init) {
console.log('处理初始化op文件')
// creatOpInit()
}
if (opts.create) {
console.log('处理根据环境和op配置文件创建op')
// creatOp()
}
})
program.parse();
命令行终端交互
咱们这个命令行工具只需要指令,没有与用户交互相关
当然你也可以搞得高级一些,比如预定义一些环境让用户选择
const inquirer = require('inquirer')
const questions = [{
type: 'list',
message: '请选择环境:',
name: 'env',
choices: [
"dev",
"fat",
"uat"
]
}]
inquirer
.prompt(
questions
)
.then(answers => {
console.log(JSON.stringify(answers,null,' '))
})
.catch(error => {
if (error.isTtyError) {
console.log('isTtyError: ',error)
} else {
console.log('Others err: ',error)
}
})
发布npm包
现在命令行工具写好了,需要给别的同事也使用怎么办呢
总不能直接把代码包发过去,然后让同事npm link吧。所以就需要把命令行工具发布到npm源上去,同事就能npm install了,而且以后代码更新同步问题也变得简单了
登录
npm login
登录得时候可能会遇到这个问题
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: github.blog/2021-08-23-…
检查自己的源,是否是https地址
npm源地址
因为我们要发布到官方源上面,所以要确保源地址为官方地址https://registry.npmjs.com
可以通过 npm config get registry
命令查看当前 registry 源。
如需修改 registry 可通过以下四种方式:
- 在全局配置
.npmrc
,可通过命令npm config set registry= https://registry.npmjs.org/
- 在当前项目配置,在当前项目中添加配置文件
.npmrc
registry = https://registry.npmjs.org/
- 发布包时指定
--registry
选项,npm publish —registry=https://registry.npmjs.org/
- 在当前项目的
package.json
中通过publishConfig
字段指定。
"publicConfig": {
"registry": "https://registry.npmjs.org/"
}
发布
npm publish --access public
通过命令行选项 --access public
声明为公有包