nodejs - npm run原理

文章目录

      • [1. 查找脚本定义](#1. 查找脚本定义)
      • [2. 环境准备](#2. 环境准备)
      • [3. 执行脚本](#3. 执行脚本)
      • [4. 生命周期脚本(如果适用)](#4. 生命周期脚本(如果适用))
      • [5. 输出与错误处理](#5. 输出与错误处理)
      • [6. 常见场景示例](#6. 常见场景示例)
        • [场景 1:运行开发服务器](#场景 1:运行开发服务器)
        • [场景 2:组合命令](#场景 2:组合命令)
        • [场景 3:跨平台兼容](#场景 3:跨平台兼容)
      • [7. 高级技巧](#7. 高级技巧)
      • [8. 与直接命令的区别](#8. 与直接命令的区别)
      • 总结

当你运行 npm run xxx 时,npm 会执行 package.jsonscripts 字段定义的名为 xxx 的脚本。这个过程涉及下面多个步骤:

1. 查找脚本定义

npm 首先会在当前项目的 package.json 文件的 scripts 字段中查找 xxx 对应的命令:

json 复制代码
{
  "scripts": {
    "xxx": "echo 'Hello World'", // 要执行的命令
    "build": "webpack --config webpack.config.js"
  }
}
  • 如果 xxx 不存在,npm 会报错:Missing script: "xxx"

2. 环境准备

  • PATH 环境变量增强

    npm 会临时将 node_modules/.bin 添加到 PATH 中,这意味着:

    • 你可以直接运行安装在项目依赖中的 CLI 工具(如 webpackeslint),而无需写完整路径(如 ./node_modules/.bin/webpack)。
    • 示例:npm run build 中的 webpack 命令会自动从 node_modules/.bin 查找。
  • 环境变量注入

    npm 会注入一些额外的环境变量,例如:

    • npm_package_name:当前项目的包名(来自 package.jsonname 字段)。
    • npm_package_version:当前版本号。
    • 可通过 process.env.npm_package_name 在脚本中访问。

3. 执行脚本

  • Shell 执行

    npm 默认在系统的默认 Shell(如 Bash、CMD/PowerShell)中执行脚本命令。

    • 在 Unix 系统(Linux/macOS)中,实际执行的是 sh -c "echo 'Hello World'"
    • 在 Windows 中,会通过 cmd.exe /C 执行。
  • 顺序执行多条命令

    如果脚本包含 &&;,npm 会按顺序执行:

    json 复制代码
    "scripts": {
      "test": "eslint . && jest"
    }
    • 先运行 eslint .,如果成功(退出码为 0),再运行 jest

4. 生命周期脚本(如果适用)

如果 xxx 是 npm 内置的生命周期脚本(如 starttestpreinstallpostinstall 等),npm 会自动触发相关的 prexxxpostxxx 钩子。

例如:

json 复制代码
{
  "scripts": {
    "prestart": "echo '准备启动...'", // 自动在 start 前执行
    "start": "node server.js",
    "poststart": "echo '服务已启动'" // 自动在 start 后执行
  }
}

运行 npm run start 时,实际执行顺序为:
prestartstartpoststart

如下:

5. 输出与错误处理

  • 输出流
    脚本的 stdoutstderr 会直接打印到终端。
  • 退出码
    • 如果脚本成功执行(退出码为 0),npm 会静默退出。
    • 如果脚本失败(非零退出码),npm 会报错并停止后续命令(在 && 链中)。

6. 常见场景示例

场景 1:运行开发服务器
json 复制代码
{
  "scripts": {
    "dev": "vite" // 直接调用 vite(来自 node_modules/.bin)
  }
}

运行 npm run dev 等价于直接执行 ./node_modules/.bin/vite

场景 2:组合命令
json 复制代码
{
  "scripts": {
    "deploy": "npm run build && rsync -av dist/ user@server:/path/to/deploy"
  }
}
  • 先执行 npm run build,成功后通过 rsync 部署。
场景 3:跨平台兼容
json 复制代码
{
  "scripts": {
    "clean": "rm -rf dist", // Unix
    "clean:win": "rmdir /s /q dist", // Windows
    "clean:all": "npm run clean || npm run clean:win"
  }
}
  • 使用 || 实现跨平台回退。

7. 高级技巧

传递参数

通过 -- 向脚本传递参数:

bash 复制代码
npm run lint -- --fix

对应的 package.json

json 复制代码
{
  "scripts": {
    "lint": "eslint ."
  }
}

实际执行:eslint . --fix

环境变量覆盖

临时覆盖环境变量:

bash 复制代码
NODE_ENV=production npm run build

脚本中可通过 process.env.NODE_ENV 读取。

静默运行

禁止输出 npm 日志(仅输出脚本内容):

bash 复制代码
npm run --silent xxx

8. 与直接命令的区别

对比项 npm run xxx 直接命令行执行(如 vite
PATH 解析 自动识别 node_modules/.bin 需全局安装或写完整路径
环境变量 注入 npm 相关变量(如版本号) 仅系统环境变量
跨平台 依赖 Shell,需处理兼容性 直接依赖系统 Shell
生命周期钩子 支持 pre/post 钩子

总结

  • npm run xxx 的本质是执行 package.json 中定义的 Shell 命令,并为其提供项目上下文(如 node_modules/.bin 路径和环境变量)。
  • 核心优势:标准化项目操作(如构建、测试),隐藏技术细节,提升团队协作一致性。
  • 最佳实践 :将常用操作(如启动、构建)封装到 scripts 中,而非依赖文档说明。

👉点击欢迎进入 我的网站

相关推荐
千里马-horse3 小时前
TypedArrayOf
开发语言·javascript·c++·node.js·napi
小笔学长3 小时前
Webpack 配置优化:提高打包速度与质量
前端·项目实战·前端开发·webpack优化·打包性能优化
优爱蛋白3 小时前
SCF His Tag 重组蛋白:c-Kit受体信号研究与干细胞培养应用的关键试剂
前端·人工智能·健康医疗
C_心欲无痕3 小时前
react - Suspense异步加载组件
前端·react.js·前端框架
JosieBook3 小时前
【Vue】05 Vue技术——Vue 数据绑定的两种方式:单向绑定、双向绑定
前端·javascript·vue.js
想学后端的前端工程师4 小时前
【浏览器工作原理与性能优化指南:深入理解Web性能】
前端·性能优化
程序员爱钓鱼4 小时前
Node.js 编程实战:错误处理与安全防护
前端·后端·node.js
Geoffwo4 小时前
Electron 打包后 exe 对应的 asar 解压 / 打包完整流程
前端·javascript·electron
柒@宝儿姐4 小时前
vue3中使用element-plus的el-scrollbar实现自动滚动(横向/纵横滚动)
前端·javascript·vue.js