通过vue create xxx 学习脚手架运行原理
前言
以vue create xxx命令为入口,探索脚手架背后的原理。常见经典的面试题:《当我们在终端输入vue create xxx创建项目时,发生了什么?》,要搞清楚这个问题,就需要了解脚手架命令执行的过程。
开始
首先全局安装@vue/cli
npm install @vue/cli -g
创建项目
vue create vue-demo

此时,就会执行对应的命令开始创建项目了,我们将这段语句分为三段
vue代表了主命令create代表了command子命令,也可以理解为是一个动作vue-demo代表了command的param,就是对应子命令的参数
说到这里,其实我们npm install @vue/cli -g也是可以按照这个规律去拆解
npm主命令install子命令@vue/cli子命令参数-g这里叫做option,可以理解为配置。它是--global的简写,所以全拼时是两条杠--global,简写是一条杠-g,常见的还有:--help/-h或者--version/-v等
那为什么我们在终端输入vue或者npm等命令时,终端可以识别的出来呢?
为什么终端认识vue命令
我们可以通过which命令来找到vue命令(实际这里是注入到了全局环境变量中)执行脚本的位置
which vue
要想知道有什么包注入了环境变量,我们先看一下全局安装了什么包:
npm list -g -deptch -0
以下是我装的全局npm包
这些包都可以通过which命令来查看:

所以可以用一句话概括就是:在终端输入vue时,终端去寻找注入的全局环境变量,找到之后,执行其对应所在环境变量的脚本位置。 我这里对应的就是:
/Users/fengxiaodong/.nvm/versions/node/v18.16.0/bin/vue
那有的同学会疑问,为什么全局安装的是@vue/cli,但是却添加的命令是vue呢?这个问题我们留到后面解释。
vue脚本
我们进入vue脚本位置的目录,这里是所有全局npm包的命令目录,都被放在了bin文件夹下
除了vue命令外,还可以看到其他的命令,如上面提到的npm和pnpm命令。
lrwxr-xr-x 1 fengxiaodong staff 39B 1 20 18:21 vue -> ../lib/node_modules/@vue/cli/bin/vue.js
通过上面这条信息,我可以得出以下结论:
vue命令执行的是:../lib/node_modules/@vue/cli/bin/vue.js脚本- 通过软链接的方式执行,因为前面有
lrwxr-xr-x标识

回到上层目录中,进一步分析得出:

- 我们的
npm包都被安装在对应的node版本目录下(v.18.16.0) bin目录是全局命令所在的文件夹目录lib目录是全局命令执行的软链接对应的文件的目录(全局包安装的真实位置)
我们通过vscode查看这个目录位置,找到了脚本文件vue.js

最终结论,我们可以用一张图概括:

- 在终端输入
vue命令 - 在环境变量中找到了
vue命令 - 终端根据
vue命令链接到实际文件vue.js - 终端利用
node执行vue.js vue.js解析command和optionvue.js执行command- 执行完毕,创建项目,退出执行
这里除了上面留下的疑问:为什么全局安装@vue/cli后却添加了vue命令;我们又多了一个疑问:为什么vue命令指向一个js文件,我们却可以直接通过vue去执行它?
为什么全局安装@vue/cli添加的却是vue命令?
前面内容已经介绍过,可以通过vscode打开vue.js,实际就是在node_modules下安装的@vue/cli目录,打开package.json,就可以看到bin的配置
bin字段就是用来指定各个内部命令对应的可执行文件的位置,这里写的是vue,对应的文件就是bin/vue.js。所以这就是为什么安装了@vue/cli,却添加的是vue命令的原因,如果我写的是:
{
haha: 'bin/vue.js'
}
那么添加的就是haha命令,初始化项目可能就变成了:
haha create xxx
总结一下:当全局安装@vue/cli时,首先会把这个这个npm包下载到当前node版本的lib/node_modules目录下,同时如果配置了bin,那么则会在当前node版本的bin目录下创建一个软链接,指向这个lib目录中配置的文件vue.js,所以这个关系就理清楚了。
为什么vue命令指向一个js文件,却可以通过vue去执行它?
我们都知道,正常运行某个.js文件可以通过node xxx.js执行,利用的就是node解析器的能力,所以理论上应该是node vue.js才对,那为什么可以用的却是vue呢?
我们在终端输入vue,会得到脚手架的信息

这个结果跟直接执行which vue的路径是一样的

所以执行vue命令时,首先去环境变量中找到vue是否被注册;输入一个不存在的命令,则会提示command not found

但我们都知道which vue的路径不是真实的路径,只是一个软链接,真实的脚本文件是:vue.js
进入这个文件,可以发现这段语句(#!/usr/bin/env node),这个的作用是什么呢?

我们正常来说,自己的文件是没办法直接在终端上执行的,例如现在有一个haha.js

随意输入一段代码

执行这个文件,会显示没有权限,因为只有可读


通过chmod 777 haha.js添加可写权限

但是直接执行这个文件,还是无法输出,必须使用node去执行

但是如果在这个文件上方加入了这段代码:#!/usr/bin/env node

我们就可以直接执行文件了

其实这等同于使用 /usr/bin env node ./haha.js

所以这三个方式的执行结果都是一样的
- 使用
node执行haha.js - 在
haha.js里面写入#!/usr/bin/env node后直接执行 - 使用
/usr bin/env node执行haha.js
那么/usr/bin/env是什么呢?在终端输入这段语句,得到的是全部的环境变量信息

而/usr/bin/env node则表示使用环境变量中node变量,所以上面总结的三种方式实际上都是使用node去执行这个文件
但是目前只能直接执行haha.js,而不是通过haha命令去执行,如果想和直接输入vue一样直接执行vue.js,是如何做到的呢?

我们期望直接输入haha就可以执行haha.js,这个时候就需要去创建软链接了,我们回到当前node版本的bin目录

通过ln -s的方式创建软链接

这样就成功的创建了一个软链接了

我们去到任意目录,输入haha,都可以成功执行vue-demo/haha.js文件了

总结一下:为什么vue命令指向的是vue.js文件,却可以通过vue去执行?原因就是因为,vue命令在bin目录下存在软链接地址,且这个地址的执行文件vue.js中有这段代码:#!/usr/bin/env node,所以在终端输入vue时,是使用环境变量node去执行了vue.js
总结
整篇文章介绍了@vue/cli从安装到执行的背后原理,理解这个背后原理对我们日后写脚手架有很大的帮助,感谢您的阅读。
转载自:https://juejin.cn/post/7325733245165355049