1. 基本概念

npm run 用於執行在 package.json 文件的 scripts 字段中定義的腳本命令。

{
  "name": "my-project",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest",
    "build": "webpack --mode=production"
  }
}

2. 工作流程詳解

2.1 命令解析階段

npm run script-name
  • npm 解析命令,提取腳本名稱
  • 查找當前項目的 package.json 文件

2.2 腳本查找過程

# npm 內部查找邏輯 1. 檢查 package.json 中的 scripts 字段 2. 如果找到對應腳本,準備執行環境 3. 如果未找到,檢查預定義腳本(start, test 等) 4. 如果都不存在,報錯退出

2.3 環境準備階段

# npm 會做以下準備工作: - 創建子進程執行環境 - 設置 NODE_ENV 環境變量(如果未設置) - 將 ./node_modules/.bin 添加到 PATH 環境變量開頭 - 設置進程特定的環境變量

3. PATH 環境變量處理

這是 npm run 最重要的特性之一:

# 執行前 PATH 示例: /usr/local/bin:/usr/bin:/bin # 執行時 PATH 變為: ./node_modules/.bin:/usr/local/bin:/usr/bin:/bin

這意味着:

  • 本地安裝的依賴包中的可執行文件可以直接使用
  • 不需要全局安裝工具(如 webpack、jest 等)

4. 生命週期腳本

npm 支持自動執行的生命週期腳本:

{
  "scripts": {
    "prestart": "echo '準備啓動...'",
    "start": "node server.js",
    "poststart": "echo '啓動完成!'",
    
    "pretest": "echo '準備測試...'",
    "test": "jest",
    "posttest": "echo '測試完成!'"
  }
}

執行 npm run test 時的順序:

prestart → start → poststart

5. 環境變量傳遞

5.1 內置環境變量

// 在腳本中可以訪問的環境變量:
process.env.npm_package_name      // 包名
process.env.npm_package_version   // 版本號
process.env.npm_package_scripts_build // build腳本內容
process.env.NODE_ENV              // 環境變量

5.2 自定義環境變量

# 設置環境變量執行腳本
NODE_ENV=production npm run build

# 或者在 package.json 中
{
  "scripts": {
    "build:prod": "NODE_ENV=production webpack"
  }
}

6. 參數傳遞

6.1 向腳本傳遞參數

npm run script-name -- --arg1 value1 --arg2 value2

示例:

{
  "scripts": {
    "serve": "webpack serve"
  }
}
npm run serve -- --port 8080 --host 0.0.0.0
# 實際執行: webpack serve --port 8080 --host 0.0.0.0

6.2 在腳本中使用參數

{
  "scripts": {
    "deploy": "node deploy.js",
    "deploy:env": "node deploy.js --env $npm_config_env"
  }
}
npm run deploy:env --env=production

7. 實際工作流程示例

7.1 完整執行流程

# 用户輸入
npm run dev

# npm 內部執行流程: 1. 讀取 package.json 2. 找到 scripts.dev = "nodemon server.js" 3. 檢查是否有 predev 腳本並執行 4. 將 ./node_modules/.bin 添加到 PATH 5. 創建子進程執行 "nodemon server.js" 6. 檢查是否有 postdev 腳本並執行 7. 返回執行結果

7.2 複雜腳本示例

{
  "scripts": {
    "prebuild": "rimraf dist && mkdirp dist",
    "build": "webpack --mode=production",
    "postbuild": "node ./scripts/notify.js",
    "dev": "concurrently \"npm run server\" \"npm run client\"",
    "server": "nodemon server.js",
    "client": "webpack serve --hot"
  }
}

8. 高級特性

8.1 跨平台兼容性

{
  "scripts": {
    "clean": "rm -rf dist",           // Unix 系統
    "clean:win": "rmdir /s /q dist",  // Windows 系統
    "clean:cross": "rimraf dist"      // 跨平台解決方案
  }
}

8.2 條件執行

{
  "scripts": {
    "build": "webpack",
    "build:analyze": "npm run build -- --analyze",
    "deploy": "npm run build && npm run test && node deploy.js"
  }
}

8.3 使用工具函數

{
  "scripts": {
    "setup": "npm install && npm run build && npm run test",
    "reset": "npm run clean && npm install && npm run build",
    "ci": "npm ci && npm run test:coverage"
  }
}

9. 調試和排查

9.1 查看可用腳本

npm run
# 或
npm run --silent

9.2 調試腳本執行

# 查看實際執行的命令
npm run build --dry-run

# 顯示詳細日誌
npm run build --loglevel verbose

9.3 錯誤處理

{
  "scripts": {
    "build": "webpack || echo '構建失敗'",
    "test": "jest --passWithNoTests",
    "deploy": "npm run build && npm run test && node deploy.js"
  }
}

總結

npm run 的工作機制可以概括為:

  1. 解析階段:讀取 package.json 中的 scripts 配置
  2. 準備階段:設置環境變量,修改 PATH
  3. 執行階段:按順序執行生命週期腳本
  4. 清理階段:返回執行結果,恢復環境