这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

npm 是 node 捆绑的依赖管理器,常用程度可想而知。那么你每天都在 npm/yarn run 的命令到底是如何运行项目的呢?

前端项目中运行 npm run xxx 的时候发生了什么?
大家都知道目前的 node 是捆绑 npm 的。npm 是 node 的依赖管理器,虽然它不是唯一的选择,我们还有 pnpm/yarn/cnpm/ni 。

但是,的依赖管理器都是在解决 npm 的某个痛点。对于 npm 依赖声明文件 ​

package.json​

本身是基本没有变化的。

例如我们可以使用 ​

npm run serve​

运行某个命令, 也可以使用 ​

yarn serve​

​ 运行某个命令。

可以看到在这个地方 yarn 可以省略 run 这个参数。

但是,他们都只是对 ​

​package.json​

进行解析而已,例如下面的文件,当运行 ​

npm run serve​

时,其实就是运行该 json 文件中的 ​

scripts​

下的 ​

​serve​

键对应的命令。

{
"name": "h5",
"version": "1.0.7",
"private": true,
"scripts": {
"serve": "vue-cli-service serve"
},
"dependencies": {
"axios": "^0.19.2",
"vuex": "^3.4.0"
},
"devDependencies": {
"node-sass": "^4.12.0"
}
}

上面说是 ​​命令​
​ 只是用于方便理解,例如:

npm run server
# 类似于在命令行运行以下命令
vue-cli-service serve

通过 npm run 与直接运行命令的区别

还是用上面的配置来描述:

{
"scripts": {
"serve": "vue-cli-service serve"
}
}

npm 在运行 ​

vue-cli-service serve​

这条命令的时候,会先在当前 ​

node_modules/.bin​

下面看有没有同名的可执行文件,如果有,则使用其运行。

这里我们可以打开这个目录看看:

如果直接在命令行中运行 ​

​vue-cli-service serve​

这条命令,是不会从 node_modules 中查找可执行程序的。

运行可执行文件

那么什么叫可执行文件呢?上面的图中有很多个同名的 vue-cli-service ,到底是运行哪个?

我们先来分析这几个文件怎么来的?

例如 ​

@vue/cli-service​

有以下 ​

package.json​

文件,注意 bin 字段,当我们运行 ​

​npm i @vue/cli-service​

这条命令时,npm 就会在 ​

​node_modules/.bin/​

目录中创建好以 ​

​vue-cli-service​

为名的几个可执行文件了。

{
"name": "@vue/cli-service",
"version": "4.4.6",
"description": "local service for vue-cli projects",
"main": "lib/Service.js",
"typings": "types/index.d.ts",
"bin": {
"vue-cli-service": "bin/vue-cli-service.js"
}
}

对于可执行​这个定义,每个系统不一样。在 windows 系统上,可执行文件是通过组策略和环境变量决定的。

使用 ​

set pathext​

可以查看 ​

pathext​

这个环境变量,他定义了可以作为可执行文件的后缀。

# 查看可执行文件后缀
set pathext

由上面的配置可以发现,我们常见的 exe 也在其中,这个可执行文件在 windows 上,在命令行中输入文件名或双击时即可以运行。

在 unix 系统上面,是通过设置文件的属性为可执行,再在文件中的第一行声明解释器来运行的。

如果我们在 cmd 里运行的时候,windows 一般是调用了 ​

​vue-cli-service.cmd

这个文件,这是 windows 下的批处理脚本:

@ECHO off
SETLOCAL
CALL :find_dp0 SET _maybeQuote="
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET _maybeQuote=
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
) %_maybeQuote%%_prog%%_maybeQuote% "%dp0%\..\_@vue_cli-service@4.4.6@@vue\cli-service\bin\vue-cli-service.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b

所以当我们运行 ​

​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

这里多提了下,在 windows 中 cmd 脚本使用得比较多,兼容性也较好。 powerShell 虽然比较强大,但他运行命令的方式由于和 cmd 命令有较大不同,这会导致你常常搞不清什么命令应该在什么解释器里运行。

示例:运行命令的方式不兼容

示例:windows 很多系统会默认禁止此脚本运行,导致 npm 命令运行错误

所以如果遇到 powerShell 相关错误时建议用 cmd 试试。

注入相关运行时信息

这一节我们通过调试 npm 的源码来进行说明。

首先我们在 ​ ​mockm​​ 这个前端接口联调工具的源码中先来个 debugger, 注意有从 process.env 中获取 NPM_CONFIG_REGISTRY 这个环境变量,这是 npm 安装时可配置的镜像地址。

然后我们再看一下这个环境变量,在当前系统中是没有定义的。

让我们开始调试 mockm package.json 中的 scripts ​

npm run s2​
{
"scripts": {
"s2": "node run.js remote --config=D:/git2/mockm/server/example/full.mm.config.js",
}
}

为了节省篇幅,这里直接断点在关键地点:

这是 npm@v6.x 的源码,可以发现 npm 使用了 ​ ​npm-lifecycle​​ 这个依赖来运行的子进程调用我们的 ​

run.js​

文件。

在通过 spawn 运行 run.js 的时候,同时设置了进程相关的一些信息,这是由 node 原生支持的。

例如刚刚说到的 NPM_CONFIG_REGISTRY 环境变量。

下面把继续进入下一个断点, run.js 文件:

可以发现子进程成功获取了父进程给予的信息。

总结

运行 npm run xxx
的时候,npm 会先在当前目录的 node_modules/.bin 查找要执行的程序,如果找到则运行;
没有找到则从全局的 node_modules/.bin 中查找,npm i -g xxx
就是安装到到全局目录;
如果全局目录还是没找到,那么就从 path 环境变量中查找有没有其他同名的可执行程序。

本文转载于:

https://blog.51cto.com/u_15077533/4531157

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--前端项目中运行 npm run xxx 的时候发生了什么?的更多相关文章

  1. 三面面试官:运行 npm run xxx 的时候发生了什么?

    事情是这样的,直接开讲 面试官:npm run xxx的时候,发生了什么?讲的越详细越好. 我(心想,简单啊): 首先,DNS 解析,将域名解析成 IP 地址,然后 TCP 连接,TCP 三次握手.. ...

  2. React中使用create-react-app创建项目,运行npm run eject建立灰度报错

    我在运行npm run eject建立测试环境和正式环境时候报错 这里的问题是是脚手架添加.gitgnore文件,但是却没有本地仓库,按照以下顺序就可以正常使用 git add . git commi ...

  3. react创建项目后运行npm run eject命令将配置文件暴露出来时报错解决方法

    最近在用create-react-app创建项目,因要配置各种组件,比如babel,antd等, 需要运行npm run eject命令把项目的配置文件暴露出来,但是还是一如既然碰到报错,因为是在本地 ...

  4. create-react-app创建项目后运行npm run eject命令报错解决办法

    最近在用create-react-app创建项目,因要配置各种组件,比如babel,antd等, 需要运行npm run eject命令把项目的配置文件暴露出来,但是还是一如既然碰到报错,因为是在本地 ...

  5. 使用create-react-app命令创建一个项目, 运行npm run eject报错

    解决方法: 先 git add . 然后 git commit -m ‘init’ 然后再npm run eject

  6. Vue项目中执行npm run dev 不报错也不显示点击的地址链接

    问题描述: 输入npm run dev 没有报错也没有显示可以点击的地址链接,如下图: 解决方法: 具体配置: autoOpenBrowser默认为false,改为true.重新 npm run de ...

  7. react 记录:运行npm run eject命令暴露配置文件都报这个错误

    问题: react 使用create-react-app命令创建一个项目,运行npm run eject命令暴露配置文件都报这个错误 原因:主要是脚手架添加 .gitgnore文件,但是却没有本地仓库 ...

  8. 在 ASP.NET Core 项目中使用 npm 管理你的前端组件包

    一.前言 在项目的前端开发中,对于绝大多数的小伙伴来说,当然,也包括我,不可避免的需要在项目中使用到一些第三方的组件包.这时,团队中的小伙伴是选择直接去组件的官网上下载,还是图省事直接在网上搜索,然后 ...

  9. create-react-app创建项目后,运行npm run eject报错解决方法

    运行npm run eject报错解决方法 主要问题是脚手架添加.gitgnore文件,但是却没有本地仓库,使用以下命令操作以下就可以了 git init git add . git commit - ...

  10. 结合docker发布前端项目(基于npm包管理)的shell脚本

    结合docker发布前端项目(基于npm包管理)的shell脚本 本教程依据个人理解并经过实际验证为正确,特此记录下来,权当笔记. 注:基于linux操作系统 目前主流的前后端分离的项目中,常常在部署 ...

随机推荐

  1. 2023年多校联训NOIP层测试7+【LGR-149-Div.3】洛谷基础赛 #2 & qw Round -1

    普及模拟3 \(T1\) 最大生成树 \(100pts\) 简化题意:给定一个 \(n(1 \le n \le 1 \times 10^5)\) 个点的完全图,给定各点的点权 \(a_i(1 \le ...

  2. Ubuntu18.04 Server部署Flannel网络的Kubernetes

    准备服务器 ESXi6.5安装Ubuntu18.04 Server, 使用三台主机, 计划使用hostname为 kube01, kube02, kube03, 配置为2核4G/160G, K8s要求 ...

  3. Js中Math对象

    Js中Math对象 Math是一个内置对象,它拥有一些数学常数属性和数学函数方法,Math用于Number类型,其不支持BigInt. 描述 Math不是一个函数对象,也就是说Math不是一个构造器, ...

  4. nginx配置反向代理缓存

    说明 最近运维一个网站里面含有不经常变化的小图片,而每次请求都需要调用file接口获取不太合适.所以就想利用nginx的反向代理缓存来减轻服务接口的请求压力. 工作原理 Nginx反向代理缓存,当客户 ...

  5. win32-WH_KEYBOARD的使用

    我们使用WH_KEYBOARD来禁用记事本的ALT的按键 .cpp #include <Windows.h> #include <stdio.h> #include <t ...

  6. java个人博客

    效果浏览 首页 详情页 Aboutme 后台管理 管理/添加博客 添加分类 管理员管理 友情链接 访问地址 前台地址http://localhost 后台地址:http://localhost/adm ...

  7. 【八股cover#3】计网 Q&A与知识点

    计网知识点Q&A 简历cover 1.TCP/IP网络模型 网络模型 ​ TCP/IP 协议族,它是一个分层.多协议的通信体系. ​ TCP/IP协议族是一个四层协议系统,自底而上分别是数据链 ...

  8. CentOS系统下,配制nginx访问favicon.ico

    sudo vim /etc/nginx/nginx.conf 添加以下配制: # set site faviconlocation /favicon.ico { root html;} 完整配置如下: ...

  9. 【Azure 事件中心】Kafka 生产者发送消息失败,根据失败消息询问机器人得到的分析步骤

    问题描述 Azure Event Hubs -- Kafka 生产者发送消息存在延迟接收和丢失问题, 在客户端的日志中发现如下异常: 2023-06-05 02:00:20.467 [kafka-pr ...

  10. 使用秘籍|如何实现图数据库 NebulaGraph 的高效建模、快速导入、性能优化

    本文整理自 NebulaGraph PD 方扬在「NebulaGraph x KubeBlocks」meetup 上的演讲,主要包括以下内容: NebulaGraph 3.x 发展历程 NebulaG ...