ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浅析有关运行npm run serve时发生了什么的5个问题出发解析npm run的执行原理

2022-05-28 20:00:37  阅读:236  来源: 互联网

标签:npm bin vue run cli service node 浅析


一、npm run serve时发生了什么?灵魂5问

1、npm run xxx 的时候,首先会去项目的 package.json 文件里找 scripts 里对应的 xxx,然后执行 xxx 的命令,例如启动vue项目 npm run serve 的时候,实际上就是执行了 package.json 文件里 scripts 下的 serve 对应的 vue-cli-service serve 这条命令

2、那为什么不直接执行 vue-cli-service serve 而要执行 npm run serve 呢?

  因为直接执行vue-cli-service serve,会报错,因为操作系统中没有存在vue-cli-service这一条指令

3、那既然vue-cli-service这条指令不存在操作系统中,为什么执行npm run serve时,也就是相当于执行了vue-cli-service serve ,为什么这样它就能成功,而且不报指令不存在的错误呢?

  我们重点关注下这个问题:为什么执行npm run serve时可以成功,而且不报指令不存在的错误呢?

  因为我们在安装依赖的时候,是通过 npm i xxx 来执行的,例如 npm i @vue/cli-service,npm 在安装这个依赖的时候,就会在 node_modules/.bin/ 目录中创建好 vue-cli-service 为名的几个可执行文件了。

  .bin 目录,这个目录不是任何一个 npm 包目录下的文件,表示这是一个个软链接,打开文件可以看到文件顶部写着 #!/bin/sh ,表示这是一个脚本

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  exec "$basedir/node"  "$basedir/../@vue/cli-service/bin/vue-cli-service.js" "$@"
else 
  exec node  "$basedir/../@vue/cli-service/bin/vue-cli-service.js" "$@"
fi

  由此我们可以知道,当使用 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 作为参数传入)

4、.bin 目录下的文件表示软连接,那这个bin目录下的那些软连接文件是哪里来的呢?它又是怎么知道这条软连接是执行哪里的呢?

  我们可以直接在新建的vue项目里面搜索vue-cli-service

  可以看到,它存在项目的 package-lock.json 文件中,从 package-lock.json 中可知,当我们npm i 整个新建的vue项目的时候,npm 将 bin/vue-cli-service.js 作为 bin 声明了。

注意:bin字段不是在自己项目的package.json文件里面,而是在库的源代码中的package.json里面,用于在安装时创建软链指向bin中的地址

在 npm i 安装时写入到了项目的 package-lock.json 里

  所以在 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文件来执行。

5、刚刚看到在node_modules/bin中有三个vue-cli-service文件,为什么会有三个文件呢?

  如果我们在 cmd 里运行的时候,windows 一般是调用了 vue-cli-service.cmd 这个文件,这是 windows 下的批处理脚本。

  所以当我们运行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

6、总结:

(1)运行 npm run xxx的时候,npm 会先在当前目录的 node_modules/.bin 查找要执行的程序,如果找到则运行;

(2)没有找到则从全局的 node_modules/.bin 中查找,npm i -g xxx就是安装到到全局目录;

(3)如果全局目录还是没找到,那么就从 path 环境变量中查找有没有其他同名的可执行程序。

二、当输入 npm run 后发生了什么

  在前端开发的工作当中,使用 npm run dev 的命令启动本地开发环境,是再正常不过的事了。那么,当输入完类似 npm run xxx 的命令后,究竟是如何触发各种构建工具的构建命令以及启动 Node 服务等功能的呢?

  首先我们知道,Node 作为 JavaScript 的运行时,可以把 .js 文件当做脚本来运行,像这种:node index.js

  当我们使用 npm 来管理项目时,会在根目录下生成一个 package.json 文件,其中的 scripts 属性,就是用于配置 npm run xxx 命令的,比如我有如下配置:
// package.json
{
  // ...
  "scripts": {
    "start": "node ./src/index.js",
    "build": "react-scripts build",
  },
  // ...
}

  当执行 npm start 时,对于 npm 来说,相当于执行 npm run start ,则映射为 scripts 属性下的 start 命令,即

npm start
# 相当于
npm run start
# 相当于
node ./src/index.js

  这个比较好理解,就是直接使用全局安装的 Node 命令来执行了 ./src 目录下的 index.js 文件而已。

  如上面类似,执行 npm run build 即相当于执行 react-scripts build 命令。这个命令,是使用 create-react-app 搭建 React 项目时默认配置的。与 Node 不同,react-scripts 并没有全局安装,怎么就能直接执行呢?

  这时我们不妨看一下,使用 create-react-app 搭建的项目(使用 vue-cli 搭建的项目也一样),在 npm install 后,其 node_modules 目录下面的样子:

  如图可以看到有一个 .bin 目录,这个目录不是任何一个 npm 包。目录下的文件,右面都有一个小箭头(VS Code 上这样显示),表示这是一个软链接,打开文件可以看到文件顶部写着 #!/user/bin/env node ,表示这是一个通过使用 Node 执行的脚本。

  由此我们可以知道,当使用 npm run build 执行 react-scripts build 时,虽然没有安装 react-scripts 的全局命令,但是 npm 会到 ./node_modules/.bin 中找到 react-scripts.js 文件作为 Node 脚本来执行,则相当于执行了 ./node_modules/.bin/react-scripts build(最后的 build 作为参数传入)。
npm run build
# 相当于
./node_modules/.bin/react-scripts build

  前面说过,react-scripts 是一个软链接,那么它的指向是哪里,又是怎么来的呢?

  我们可以在 node_modules 目录下,直接找到 react-scripts 包,查看其目录结构和 package.json 如下:

  从 package.json 中可知,这个包将 ./bin/react-scripts.js 作为 bin 声明了。所以在 npm install 时,npm 读到该配置后,就将该文件软链接到 ./node_modules/.bin 目录下,而 npm 还会自动把node_modules/.bin加入$PATH,这样就可以直接作为命令运行依赖程序和开发依赖程序,不用全局安装了。

  假如我们在安装包时,使用 npm install -g xxx 来安装,那么会将其中的 bin 文件加入到全局,比如 create-react-appvue-cli ,在全局安装后,就可以直接使用如 vue-cli projectName 这样的命令来创建项目了。

  第二节来源于:https://juejin.cn/post/6971723285138505765

  还有这篇文章,可以学一下:https://juejin.cn/post/7025908145650139144

标签:npm,bin,vue,run,cli,service,node,浅析
来源: https://www.cnblogs.com/goloving/p/16306638.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有