运行 npm run xxx 的时候发生了什么?
liuian 2025-01-05 18:42 107 浏览
前言:
面试官:npm run xxx的时候,发生了什么?讲得越详细越好。
我(心想,简单啊): 首先,DNS 解析,将域名解析出来 IP 地址,然后 TCP 连接,TCP 三次握手...
面试官:停停,我问的不是从URL输入到页面展现到底发生什么?,是npm run xxx的时候,发生了什么。
执行原理
使用npm run script执行脚本的时候都会创建一个shell,然后在shell中执行指定的脚本。
这个shell会将当前项目的可执行依赖目录(即node_modules/.bin)添加到环境变量path中,当执行之后之后再恢复原样。就是说脚本命令中的依赖名会直接找到node_modules/.bin下面的对应脚本,而不需要加上路径。
执行顺序
一个npm脚本可以执行多个任务,这些任务之间可以指定不同的执行顺序。& 并行执行顺序,同时执行
"dev":"node test.js & webpack"&&继发顺序,执行前面之后才可以执行后面
"dev":"node test.js && webpack"npm run dev 发生了什么
以vue cli 3配置为例,
"scripts":{
"dev":"vue-cli-serviceserve",
"serve":"vue-cli-serviceserve",
"build":"vue-cli-servicebuild",
"lint":"vue-cli-servicelint"
}
执行npmrundev后
npm会去package.json里边的scripts字段里找dev这个命令
如果配置了的话,就会执行对应的配置vue-cli-serviceserve
vue-cli-service也是一个命令。
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这一条指令
面试官: 哦,对对对,不错不错!
那为什么执行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 目录,这个目录不是任何一个 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 这样的命令来创建项目了。
那么为啥在执行start命令的时候,可以默认执行node server.js命令呢?那是因为node是已经全局安装了,可以直接被调用。这里多一嘴,如果scripts字段里没有start,也不会报错,会去默认执行node server.js命令。
p.s.:如果我们只运行了npm run命令,那么就会去执行scripts字段里所有的脚本命令。
.bin目录下的软链接
我们继续往下看,既然.bin目录下的执行文件是一个个软链接,那么这些软链接文件是哪里来的呢?npm又是怎么知道这些软链接是指向哪里呢?
我们可以直接在项目根目录下的package-lock.json文件里搜索ng.js,可以看到npm在install的时候,就将bin/ng.js作为bin声明了:
因此在npm安装的时候,就把bin/ng.js文件软链接到了./node_modules/.bin 目录下,而npm 还会自动把node_modules/.bin加入$PATH 变量内,这样ng 就可以不用全局安装了,直接作为命令来运行、开发依赖程序。也就是说,软链接相当于是一种映射,在执行npm run xxx的时候,就会到node_modules/.bin目录里找到对应的映射文件,然后再找到相对应的js文件来执行。
而如果我们想不用软链接的方式,直接使用全局安装的命令的话,我们就需要在安装包的时候,使用npm install -g xxx来安装这个依赖,那么就会将xxx其中的bin文件加入到全局中;这样就可以和node一样,直接使用诸如xxx build这样的命令了。
四个可以简写的脚本执行命令
npm start === npm run start
npm stop === npm run stop
npm test === npm run test
npm restart === npm run stop && npm run restart && npm run startwebpack-dev-server:
webpack-dev-server主要是启动了一个使用express的Http服务器。它的作用主要是用来伺服资源文件。此外这个Http服务器和client使用了websocket通讯协议,原始文件作出改动后,webpack-dev-server会实时的编译,但是最后的编译的文件并没有输出到目标文件夹,,实时编译后的文件都保存到了内存当中。因此很多同学使用webpack-dev-server进行开发的时候都看不到编译后的文件
运行常会出现的一些错误
一:运行的时候出现npm resource busy or locked,
解决方法:在网上搜的时候会说modules那个文件出错,但是卸载之后重新安装还是不行的,如下:
也可以试试,然后又根据网上的方法安装了一些其他东西,但是还是一直报那样的错,最后,就又重新建个文件,把项目又拉一遍,然后弄住运行住,没有什么的时候当时就安装上,后来就没有再报这个错了。
二. Please restart this script from an administrative PowerShell!
问题场景:在cmd窗口输入npm install --global --production windows-build-tools报错
Please restart this script from an administrative PowerShell!,
解决方法:以管理员身份运行cmd窗口
三.Syntax Error: Error: PostCSS received undefined instead of CSS string
问题场景:此问题也一般出现在更新了git文件后,由于其他开发人员安装了sass-loader版本,导致本地的sass-loader版本不兼容问题
解决方法:手动卸载当前的node-sass和sass-loader版本,重新安装指定版本
(如果当前的安装不小心污染了本地package.json文件,可查看过往git版本记录,安装对应版本即可)
四、Cannot find module 'bower'( Cannot find module 'XXX')
找不到bower (缺少这个)
解决办法:npm install bower (npm install XXX)
这种情况一般是少安装某个依赖包所导致的,其实这个应该算比较简单, 可以直接运行 npm install 然后在 npm run dev 或者 npm run start 试一下。
总结
- 运行 npm run xxx的时候,npm 会先在当前目录的 node_modules/.bin 查找要执行的程序,如果找到则运行;
- 没有找到则从全局的 node_modules/.bin 中查找,npm i -g xxx就是安装到到全局目录;
- 如果全局目录还是没找到,那么就从 path 环境变量中查找有没有其他同名的可执行程序。
参考文章
blog.51cto.com/u_15077533/… juejin.cn/post/697172…
- 上一篇:深入了解Npm
- 下一篇:手把手教你安装elasticsearch
相关推荐
-
- 谷歌在线浏览器(谷歌在线代理浏览器)
-
1.打开谷歌浏览器设置,点击右上方按钮2.点击设置3.点击同步功能和Google服务4.点击登录Chrome即可手机和电脑都可以下载谷歌浏览器。登录时需要创建一个账号和邮箱,需要记住自己的账号和密码,同时手机和电脑可以同步。...
-
2026-01-08 09:05 liuian
- vs2019微软官网下载(microsoft visual studio官方下载)
-
原因是可能您的电脑环境不符合VS2022安装要求,或者您的安装程序出现了问题。所以导致了安装失败。同时,您可以尝试重新下载安装程序,或者检查电脑所有驱动程序是否更新到最新版本,或者关闭杀毒软件等其他可...
- 家用无线路由器哪个好(家用无线路由器哪个好用又实惠)
-
各有优劣,不能单纯的说是无线的好还是优先的好:1、有线路由器网络稳定,不会跳PING。但不能发射WiFi信号给手机上网,需要走线,受到布线约束。2、无线路由器和有线路由器最大的区别体现在和电脑的连接方...
- u盘世界十大排名(u盘全球排名)
-
1、首先主板支持u启动其次u盘空间足够再者将u盘进行引导式格式化,如usb-hdd模式(一般1g的u盘不能格zip模式)系统安装程序复制进u盘开机从u盘启动就行了。2、首先在U盘中安装java...
- 应用程序无法正常启动0xc0000006
-
Windows10中的0xc0000006映像错误 这是在Windows10中修复错误映像错误0xc0000006的方法– 【1】卸载Windows更新 几乎每个“错误映像错误”的典型原因是...
-
- qq空间说说怎么设置权限(qq空间说说在哪里设置权限)
-
1、首先在电脑上将qq软件打开,输入账号和密码登录到qq页面上。2、接着在qq的主界面点击最上方的Z进入到个人qq空间页面。3、进入到qq到空间之后,在右上角找到齿轮的图标点击它,并选择权限设置。4、接着在左侧的空间设置里面选择评论留言防骚...
-
2026-01-08 06:55 liuian
- docx是什么格式的文件(docx是什么格式的文件怎么转word)
-
docx是Office2007之后版本使用的文本格式。设置方法如下:1、首先在电脑上面找到一份word文档,将它打开。2、打开之后,在文档上面找到文件选项,点击文件进入。3、进入之后,在屏幕的下拉菜单...
-
- 苹果笔记本pro和air哪个好(苹果笔记本air与pro哪个好)
-
买苹果笔记本,买pro好,他在处理器上有一定升级。使用的是最新的处理器,所以性能表现方面会有一些优势。但是相比。它的系统比较卡顿,使用起来不是很流畅,影响日常使用,所以最好还是买后者好一些。它的性能更加稳定,各种方面都比较不错,在日常使用...
-
2026-01-08 05:55 liuian
- 笔记本一直重启开不了机怎么办
-
那就是笔记本坏掉了呀,坏掉了就去售后维修看一下呀原因及解决方法如下1.我们需要确认一下笔记本电脑是否有电。如果笔记本电脑的电量不足,就会出现无法开机的情况。此时,我们需要将电脑连接到电源插座上,充电一...
- 电脑不能开机是怎么回事
-
电脑不能开机可能有多种原因,以下是一些常见的问题和解决方法:1.电源问题:检查电源插头是否插紧,是否有电源输出。可以尝试更换电源线或电源插头。2.内部硬件故障:电脑内部硬件出现问题可能导致电脑无法...
- itunesstore下载安装(itunes下载安装教程)
-
回答如下:是的,下载和安装应用程序需要使用iTunes帐户登录。这是为了确保您有权使用该应用程序,并且可以在需要时重新安装该应用程序。您可以使用现有的iTunes帐户或创建一个新的帐户来登录。App...
- windows软件中心(win10应用中心)
-
windows安全中心是windows系统的一个安全综合控制面板,包含有防火墙状态提示,杀毒软件状态提示,自动更新提示等系统基本安全信息。Windows安全中心的前身是MicrosoftSecu...
- 苹果动态壁纸怎么设置自己的视频
-
苹果图库里的视频做成动态壁纸方法如下:1/7点击Livephoto进入处理视频工具页面后,找到并点击里面的Livephoto选项。2/7选择视频在跳转的选择页面中,选择并点击一个要进行处理的视频。3/...
-
- 查看qq密码的软件(查询qq密码软件)
-
可以按照如下方式进行查看:1、打开QQ安全中心应用,使用当前已有的QQ账号登录,登陆成功之后,点击页面右下角“工具箱”图标;2、接下来,在打开的页面中,点击“修改密码”菜单;3、最后,在打开的修改密码页面中,在网页中直接输入新的密码,点击“...
-
2026-01-08 02:05 liuian
- 一周热门
-
-
飞牛OS入门安装遇到问题,如何解决?
-
如何在 iPhone 和 Android 上恢复已删除的抖音消息
-
Boost高性能并发无锁队列指南:boost::lockfree::queue
-
大模型手册: 保姆级用CherryStudio知识库
-
用什么工具在Win中查看8G大的log文件?
-
如何在 Windows 10 或 11 上通过命令行安装 Node.js 和 NPM
-
威联通NAS安装阿里云盘WebDAV服务并添加到Infuse
-
Trae IDE 如何与 GitHub 无缝对接?
-
idea插件之maven search(工欲善其事,必先利其器)
-
如何修改图片拍摄日期?快速修改图片拍摄日期的6种方法
-
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)
