脚手架可以干啥?
不同的公司有不同的开发规范,并且通常也有自己内部的UI组件库,那么就需要一套脚手架工具来进行业务项目的一键初始化,接入公司内部的组件库、开发规范等。同时,脚手架工具还可以用来进行公司内部的前端物料创建、发布等操作。
接下来我将会从@vue/cli
入手,用一系列的文章记录总结下自己对脚手架工具的探索过程。
终端命令是如何跑起来的
在使用@vue/cli
来初始化vue
项目的时候,我们在命令行输入vue create
,然后就可以在终端看见一系列的交互提示。
那么终端是如何识别用户输入、找到对应的逻辑并执行的呢?
可执行文件
调试准备
vscode 选择“Javascript 调试终端”, 此时 vscode 会打开内置的终端,并且提示 “Debugger attached”
接着在想要进行断点调试的文件中打上断点,并运行对应文件,就可以正常捕捉到断点了。
可执行文件的注册
在@vue/cli/package.json
中我们可以看到,有个bin
字段:
在进行依赖安装时,npm
会在node_modules/.bin
文件目录下生成一个指向可执行文件bin/vue.js
的符号连接。命令行执行vue
命令时运行的逻辑就包含在此文件中。
命令行工具commander
vue
是通过package.json
中的bin
字段注册的,那么create
又是怎么识别的呢?
命令注册
可以看到,bin/vue.js
中引入了命令行工具commander,通过.command()
可以传入命令的名字、描述,.action()
则是当执行命令时需要调用的回调函数。
const { program } = require('commander');
// 通过绑定处理函数实现命令(这里的指令描述为放在`.command`中)
// 返回新生成的命令(即该子命令)以供继续配置
program
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.action((source, destination) => {
console.log('clone command called');
});
@vue/cli
的create
命令就是通过.action()
中引入../lib/create
模块并调用来实现的
在完成命令的注册后,回调函数将会保存到Commander
实例的_actionHandler
中
第二种注册命令的方式是通过可执行文件的方式实现命令。
// 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数)
// 返回最顶层的命令以供继续添加子命令
program
.command('start <service>', 'start named service')
.command('stop [service]', 'stop named service, or all if no name supplied');
vue/cli
源码并没有用到这种处理方式,这里我们通过一个小例子来测试一下这种方式的命令注册及执行过程。
创建两个可执行文件放置于bin文件夹中,并利用npm link
在node_modules/.bin
文件夹下生成两个符号链接。这里生成符号链接的目的只是为了模拟命令的可执行文件查找过程,实际上直接在命令行输入可执行文件的路径也能正常执行。
此时我们打上断点后再在命令行中输入myVue create my-app
进行调试会发现,在myVue.js
进行参数解析时,会寻找传入的myVue
是否有注册过对应create
的子命令
接着解析参数my-app
是否属于子命令,否,返回_dispatchSubcommand
继续create
子命令的执行。传入的create
子命令会在可执行文件夹中查找是否存在可执行文件命令-子命令
,即myVue-create
总结
脚手架工具主要可用于本地开发过程中的业务项目一键初始化、公司内部物料组件初始化等。经过一系列的源码调试可得知,它的运行依赖于node
环境可执行文件的执行。命令的注册可通过命令行工具库commander
的.command()
注册,命令对应的执行逻辑可通过.action()
写入回调,也可以在可执行文件夹中将逻辑写入命令-子命令
文件中。
接下来第二篇将会继续从源码角度理解总结脚手架工具是如何获取项目模板的,感谢阅读。
原文链接:https://juejin.cn/post/7238479969180876861 作者:心有猛虎细嗅达猪