三面面试官:运行 npm run xxx 的时候发生了什么?
事情是这样的,直接开讲
面试官:npm run xxx的时候,发生了什么?讲的越详细越好。
我(心想,简单啊): 首先,DNS 解析,将域名解析成 IP 地址,然后
TCP 连接,TCP 三次握手...
面试官:停停,我问的不是从URL输入到页面展现到底发生什么?,是npm run xxx的时候,发生了什么。

我(尴尬,条件反射地以为是问的八股文):emmmm,我记得 npm run xxx的时候,首先会去项目的package.json文件里找scripts 里找对应的xxx,然后执行 xxx的命令,例如启动vue项目 npm run serve的时候,实际上就是执行了vue-cli-service serve 这条命令。(好险,幸好这点常识我还是懂的)
package.json文件
{
"name": "h5",
"version": "1.0.7",
"private": true,
"scripts": {
"serve": "vue-cli-service serve"
},
}
面试官:嗯,不错,那 为什么 不直接执行vue-cli-service serve而要执行npm run serve 呢?
我(支支吾吾):emm,因为 npm run serve 比较简短,比较好写。

面试官:你再想想。
我(啊?不对吗,对哦,我想起来了): 因为 直接执行vue-cli-service serve,会报错,因为操作系统中没有存在vue-cli-service这一条指令


面试官: 哦,对对对,不错不错,哟西哟西!
我(嘿嘿,稳了,这次我要30k): 嘻嘻!

面试官:那既然vue-cli-service这条指令不存在操作系统中,为什么执行npm run serve的时候,也就是相当于执行了vue-cli-service serve ,为什么这样它就能成功,而且不报指令不存在的错误呢?
我(啊?要不你还是把我鲨了吧,不想再勉强作回答):不好意思,这个我还没了解过。
面试官:emmm,好吧,没关系,我们做下一道算法题吧:....
....
后面无关此次文章的内容,就省略过了。
面试官:好的,此处面试到此结束,我们会在一周内回复您的面试结果
哔哔哔...(电话挂断)
唉。看来是凉了
为什么执行npm run serve的时候,这样它就能成功,而且不报指令不存在的错误呢?
我赶紧问问了大佬朋友这一过程到底是发生了什么

经过一番讨论,终于找到了答案。
不服输的我,赶紧回拨了面试官的电话号码。
我:喂,面试官,您好,我已经找到答案了,可以麻烦您再听一下吗?
面试官:嗯,可以啊,请讲。
我:我们在安装依赖的时候,是通过npm i xxx 来执行的,例如 npm i @vue/cli-service,npm 在 安装这个依赖的时候,就会node_modules/.bin/ 目录中创建 好vue-cli-service 为名的几个可执行文件了。


.bin 目录,这个目录不是任何一个 npm 包。目录下的文件,表示这是一个个软链接,打开文件可以看到文件顶部写着 #!/bin/sh ,表示这是一个脚本。
由此我们可以知道,当使用 npm run serve 执行 vue-cli-service serve 时,虽然没有安装 vue-cli-service的全局命令,但是 npm 会到 ./node_modules/.bin 中找到 vue-cli-service 文件作为 脚本来执行,则相当于执行了 ./node_modules/.bin/vue-cli-service serve(最后的 serve 作为参数传入)。
面试官:可以啊,真不错,但是我还想继续问问,你说.bin 目录下的文件表示软连接,那这个bin目录下的那些软连接文件是哪里来的呢?它又是怎么知道这条软连接是执行哪里的呢?
我(窃喜,这个我们刚刚也讨论了):我们可以直接在新建的vue项目里面搜索vue-cli-service

可以看到,它存在项目最外层的package-lock.json文件中
从 package-lock.json 中可知,当我们npm i 整个新建的vue项目的时候,npm 将 bin/vue-cli-service.js 作为 bin 声明了。
所以在 npm install 时,npm 读到该配置后,就将该文件软链接到 ./node_modules/.bin 目录下,而 npm 还会自动把node_modules/.bin加入$PATH,这样就可以直接作为命令运行依赖程序和开发依赖程序,不用全局安装了。
假如我们在安装包时,使用 npm install -g xxx 来安装,那么会将其中的 bin 文件加入到全局,比如 create-react-app 和 vue-cli ,在全局安装后,就可以直接使用如 vue-cli projectName 这样的命令来创建项目了。
面试官:搜噶,也就是说,npm i 的时候,npm 就帮我们把这种软连接配置好了,其实这种软连接相当于一种映射,执行npm run xxx 的时候,就会到 node_modules/bin中找对应的映射文件,然后再找到相应的js文件来执行。
我(疯狂点头):嗯嗯,是的,就是这样
面试官:我有点好奇。刚刚看到在node_modules/bin中 有三个vue-cli-service文件。为什么会有三个文件呢?

我:如果我们在 cmd 里运行的时候,windows 一般是调用了 vue-cli-service.cmd,这个文件,这是 windows 下的批处理脚本:
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@vue\cli-service\bin\vue-cli-service.js" %*
所以当我们运行vue-cli-service serve这条命令的时候,就相当于运行 node_modules/.bin/vue-cli-service.cmd serve。
然后这个脚本会使用 node 去运行 vue-cli-service.js这个 js 文件
由于 node 中可以使用一系列系统相关的 api ,所以在这个 js 中可以做很多事情,例如读取并分析运行这条命令的目录下的文件,根据模板生成文件等。
# unix 系默认的可执行文件,必须输入完整文件名
vue-cli-service
# windows cmd 中默认的可执行文件,当我们不添加后缀名时,自动根据 pathext 查找文件
vue-cli-service.cmd
# Windows PowerShell 中可执行文件,可以跨平台
vue-cli-service.ps1
面试官:原来如此,不错嘛小伙子,短短时间内就掌握清楚了,看来学习能力很强,不错不错,我很看好你,我会催hr尽快回复你的。先这样了,拜拜
我(欣喜若狂,功夫不负有心人啊):好啊,好啊,拜拜
哔哔哔...(电话挂断)
过了三十分钟....
今天是个好日子,心想的事儿都能成,今天是个好日子,打开了家门咱迎春风...(手机铃声响起)。
我:喂,您好。
hr:您好,我是xxx公司的hr,根据你面试的优秀表现,恭喜你获得了我司的offer,经过我最大的努力,我给你争取到了最大的薪资,薪资是月薪3500,您看满意吗?
我:....
哔哔哔....(电话挂断)
tmd,c

总结
- 运行 npm run xxx的时候,npm 会先在当前目录的 node_modules/.bin 查找要执行的程序,如果找到则运行;
- 没有找到则从全局的 node_modules/.bin 中查找,npm i -g xxx就是安装到到全局目录;
- 如果全局目录还是没找到,那么就从 path 环境变量中查找有没有其他同名的可执行程序。
参考文章
https://blog.51cto.com/u_15077533/4531157
https://juejin.cn/post/6971723285138505765
三面面试官:运行 npm run xxx 的时候发生了什么?的更多相关文章
- 在mac下运行 npm run eject 出现报错问题解决方法
当使用create-react-app创建项目后,接着运行npm run eject时,如果出现下面的错误 可能是脚手架添加了.gitignore这个文件,但是没有本地仓库,可以使用以下代码解决这个问 ...
- react 记录:运行npm run eject命令暴露配置文件都报这个错误
问题: react 使用create-react-app命令创建一个项目,运行npm run eject命令暴露配置文件都报这个错误 原因:主要是脚手架添加 .gitgnore文件,但是却没有本地仓库 ...
- 使用vue框架运行npm run dev 时报错解决
使用使用vue框架运行npm run dev 时报错 如下: 原因: localhost:8080 有可能其他软件占用了,导致其他问题的出现 我们可以动态修改地址 解决: 进入项目文件的config文 ...
- mpvue使用vant Weapp运行npm run build命令打包后失效
最近在使用mpvue开发微信小程序,在开发过程中使用有赞的小程序ui框架—— vant Weapp ,至于如何使用在我个人博客中有一篇关于如何使用vant Weapp ,需要的同学请点进这里自行查看. ...
- create-react-app创建项目后运行npm run eject命令报错解决办法
最近在用create-react-app创建项目,因要配置各种组件,比如babel,antd等, 需要运行npm run eject命令把项目的配置文件暴露出来,但是还是一如既然碰到报错,因为是在本地 ...
- React中使用create-react-app创建项目,运行npm run eject建立灰度报错
我在运行npm run eject建立测试环境和正式环境时候报错 这里的问题是是脚手架添加.gitgnore文件,但是却没有本地仓库,按照以下顺序就可以正常使用 git add . git commi ...
- 运行 npm run lint -- --fix,提示:error Use the global form of 'use strict'
运行 npm run lint -- --fix,提示:error Use the global form of 'use strict',使用说明网址:https://eslint.org/docs ...
- react创建项目后运行npm run eject命令将配置文件暴露出来时报错解决方法
最近在用create-react-app创建项目,因要配置各种组件,比如babel,antd等, 需要运行npm run eject命令把项目的配置文件暴露出来,但是还是一如既然碰到报错,因为是在本地 ...
- 转载:TypeError: Cannot read property 'compilation' of undefined vue 打包运行npm run build 报错
转载自:https://www.jianshu.com/p/3f8f60e01797 运行npm run build打包时,报错如下: 我的package.json如下: { ... " ...
随机推荐
- MySQL数据库初识、下载使用(针对库、表、记录的增删改查)
今日内容概要 数据演变史 数据库软件的本质 MySQL简介 下载与安装 基本配置 基本SQL语句 内容详细 1.数据演变史 # 1.单独的文本文件 没有固定的存放位置和格式 文件名:user.txt ...
- Solution -「多校联训」数学考试
\(\mathcal{Description}\) Link. 给定 \(n\) 个函数,第 \(i\) 个有 \(f_i(x)=a_ix^3+b_ix^2+cx_i+d~(x\in[l_i, ...
- Solution -「NOI 模拟赛」出题人
\(\mathcal{Description}\) 给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\ ...
- pytest(13)-多线程、多进程执行用例
有些项目的测试用例较多,测试用例时需要分布式执行,缩短运行时间. pytest框架中提供可用于分布式执行测试用例的插件:pytest-parallel.pytest-xdist,接下来我们来学习这两个 ...
- JVM内存结构的组成、各部分功能作用
一.程序计数器 作用:是记住下一条jvm指令的执行地址 特点: 是线程私有的 不会存在內存溢出 二.虚拟机栈 每个线程运行时所需要的内存,称为虚拟机栈 每个栈由多个栈帧(Frame) 组成,对应着 ...
- CobaltStrike逆向学习系列(11):自实现 Beacon 检测工具
这是[信安成长计划]的第 11 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 检测原理 0x02 检测方案 0x03 存在的问题 0x04 解决方案 0x05 示例代码 0x06 ...
- netty系列之:channelHandlerContext详解
目录 简介 ChannelHandlerContext和它的应用 AbstractChannelHandlerContext DefaultChannelHandlerContext 总结 简介 我们 ...
- 由浅入深--MyBatis整体架构
学一门技术,做一件事不应该马上就直接进入到细节中,而是应该鸟瞰其全貌,了解它的整体架构和执行流程. MyBatis的整体架构 MyBatis的整体架构分为三层,分别是基础支持层,核心处理层和接口层,各 ...
- 60天shell脚本计划-7/12-渐入佳境
--作者:飞翔的小胖猪 --创建时间:2021年2月26日 --修改时间:2021年3月2日 说明 每日上传更新一个shell脚本,周期为60天.如有需求的读者可根据自己实际情况选用合适的脚本,也可在 ...
- Qt:QJsonDocument以及与QJsonArray、QJsonObject、QJsonValue的关联
0.说明 QJsonDocument类提供了read/write JSON文档的方法. 用QJsonDocument::fromJson()方法,可以从将一个JSON文件(或者QByteArray数据 ...