当我们执行 npm run xxx 的时候实际执行逻辑和流程

npm run dev 执行流程详解

npm run dev 最终是通过 Node.js 执行的,vite.config.ts 是一个 Node.js 模块,会被 Node.js 读取和执行。

📋 完整执行流程

1. npm run dev 命令

bash 复制代码
npm run dev

实际执行:

bash 复制代码
# npm 会查找 package.json 中的 scripts.dev
# 然后执行对应的命令
unh dev

2. unh 命令(Node.js 可执行文件)

bash 复制代码
unh dev

实际执行:

bash 复制代码
# unh 是一个 Node.js 命令行工具(CLI)
# 位于 node_modules/.bin/unh
# 实际是一个 Node.js 脚本,通过 shebang 执行:
#!/usr/bin/env node

# 或者通过 npx 执行:
npx unh dev

unh 的工作:

  1. 读取 unh.config.ts 配置文件(Node.js 模块)
  2. 解析平台参数(如 wxmp-weixin
  3. 执行 hooks(如 dev hook)
  4. 调用 Vite CLI

3. Vite CLI(Node.js 可执行文件)

bash 复制代码
# unh 内部会调用:
vite dev
# 或
npx vite dev

Vite 的工作:

  1. 读取 vite.config.ts 配置文件(Node.js 模块)
  2. 加载环境变量(.env 文件)
  3. 启动开发服务器

4. vite.config.ts 的执行

typescript 复制代码
// vite.config.ts
export default defineConfig(({ mode }) => {
  // 这段代码是在 Node.js 环境中执行的!
  const actualMode = process.env.VITE_MODE || mode
  const env = loadEnv(actualMode, process.cwd(), '')
  
  return {
    // 返回配置对象
  }
})

执行时机:

  • Node.js 环境:在 Node.js 进程中执行
  • 构建时:在启动开发服务器之前执行
  • 每次启动 :每次运行 npm run dev 都会执行

🔍 详细执行链

arduino 复制代码
npm run dev
  ↓
npm 读取 package.json
  ↓
执行: unh dev
  ↓
Node.js 执行 node_modules/.bin/unh
  ↓
unh 读取 unh.config.ts (Node.js 模块)
  ↓
unh 执行 dev hook
  ↓
unh 调用 Vite CLI
  ↓
Node.js 执行 node_modules/.bin/vite
  ↓
Vite 读取 vite.config.ts (Node.js 模块)
  ↓
vite.config.ts 中的代码在 Node.js 中执行
  ↓
loadEnv() 读取 .env 文件(Node.js fs 模块)
  ↓
返回配置对象
  ↓
Vite 启动开发服务器

💡 关键点

1. 都是 Node.js 执行

bash 复制代码
# 所有这些命令最终都是通过 Node.js 执行的:
npm run dev          # Node.js 执行 npm
unh dev              # Node.js 执行 unh
vite dev             # Node.js 执行 vite

2. 配置文件是 Node.js 模块

typescript 复制代码
// vite.config.ts
// 这是一个 Node.js 模块(CommonJS 或 ES Module)
// 会被 Node.js 的 require() 或 import() 加载

export default defineConfig(({ mode }) => {
  // 这里的代码在 Node.js 环境中运行
  // 可以使用 Node.js 的所有 API:
  console.log(process.env)        // ✅ Node.js 全局对象
  const fs = require('fs')        // ✅ Node.js 模块
  const path = require('path')    // ✅ Node.js 模块
  
  return {
    // 返回配置对象
  }
})

3. 自动读取配置文件

Vite 会自动查找配置文件:

  • vite.config.ts(TypeScript)
  • vite.config.js(JavaScript)
  • vite.config.mjs(ES Module)
  • vite.config.cjs(CommonJS)

查找顺序:

  1. 项目根目录
  2. 使用 fs 模块读取文件
  3. 使用 Node.js 的模块系统加载

4. 环境变量加载

typescript 复制代码
// vite.config.ts
const env = loadEnv(actualMode, process.cwd(), '')

loadEnv 的工作原理:

typescript 复制代码
// Vite 内部的 loadEnv 函数(简化版)
function loadEnv(mode, root, prefix) {
  // 使用 Node.js 的 fs 模块读取文件
  const fs = require('fs')
  const path = require('path')
  
  // 读取 .env.development 文件
  const envFile = path.join(root, `.env.${mode}`)
  const content = fs.readFileSync(envFile, 'utf-8')
  
  // 解析环境变量
  const env = {}
  content.split('\n').forEach(line => {
    const [key, value] = line.split('=')
    if (key.startsWith(prefix)) {
      env[key] = value
    }
  })
  
  return env
}

🎓 实际例子

例子1:npm run dev

bash 复制代码
npm run dev

执行过程:

  1. npm 解析命令

    bash 复制代码
    # npm 内部执行:
    node node_modules/.bin/unh dev
  2. unh 启动

    javascript 复制代码
    // unh 内部代码(简化)
    const config = require('./unh.config.ts')
    config.hooks.dev('h5', {})
  3. unh 调用 Vite

    bash 复制代码
    # unh 内部执行:
    node node_modules/.bin/vite dev
  4. Vite 读取配置

    javascript 复制代码
    // Vite 内部代码(简化)
    const config = require('./vite.config.ts')
    const resolvedConfig = config.default({ mode: 'development' })
  5. vite.config.ts 执行

    typescript 复制代码
    // 这段代码在 Node.js 中执行
    export default defineConfig(({ mode }) => {
      // mode = 'development'
      const env = loadEnv('development', process.cwd(), '')
      // env = { VITE_API_BASE_URL: 'https://dev-api.example.com', ... }
    
      return {
        // 返回配置
      }
    })

例子2:VITE_MODE=test npm run dev

bash 复制代码
VITE_MODE=test npm run dev

执行过程:

  1. 设置环境变量

    bash 复制代码
    # Shell 设置环境变量
    process.env.VITE_MODE = 'test'
  2. npm 执行命令

    bash 复制代码
    # npm 继承环境变量
    node node_modules/.bin/unh dev
  3. vite.config.ts 读取环境变量

    typescript 复制代码
    export default defineConfig(({ mode }) => {
      // process.env.VITE_MODE = 'test'(从环境变量读取)
      const actualMode = process.env.VITE_MODE || mode
      // actualMode = 'test'
    
      const env = loadEnv('test', process.cwd(), '')
      // 读取 .env.test 文件
    
      return {
        // 返回配置
      }
    })

🔧 技术细节

1. Node.js 模块系统

typescript 复制代码
// vite.config.ts
// 这是一个 ES Module(因为 package.json 中有 "type": "module")

export default defineConfig(...)

加载过程:

javascript 复制代码
// Vite 内部(简化)
import config from './vite.config.ts'
// 或
const config = await import('./vite.config.ts')

2. 配置文件执行时机

typescript 复制代码
// vite.config.ts
console.log('这行代码会在 Node.js 中执行')

export default defineConfig(({ mode }) => {
  console.log('这行代码也会在 Node.js 中执行')
  console.log('mode:', mode)
  
  return {
    // 配置对象
  }
})

执行时机:

  • 每次启动时 :每次运行 npm run dev 都会执行
  • Node.js 环境:在 Node.js 进程中执行
  • 构建时:在启动开发服务器之前执行

3. 环境变量访问

typescript 复制代码
// vite.config.ts
export default defineConfig(({ mode }) => {
  // ✅ 可以访问 Node.js 环境变量
  console.log(process.env.VITE_MODE)
  console.log(process.env.NODE_ENV)
  
  // ✅ 可以使用 Node.js 模块
  const fs = require('fs')
  const path = require('path')
  
  // ✅ 可以读取文件
  const packageJson = JSON.parse(
    fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8')
  )
  
  return {
    // 配置
  }
})

📊 执行流程图

arduino 复制代码
┌─────────────────────────────────────────┐
│  1. 用户输入: npm run dev                │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  2. npm 读取 package.json               │
│     scripts.dev = "unh dev"             │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  3. npm 执行: node node_modules/.bin/unh│
│     (Node.js 执行 unh 可执行文件)       │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  4. unh 读取 unh.config.ts              │
│     (Node.js 模块系统加载)              │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  5. unh 执行 dev hook                   │
│     console.log('启动开发环境...')       │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  6. unh 调用: node node_modules/.bin/vite│
│     (Node.js 执行 vite 可执行文件)       │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  7. Vite 读取 vite.config.ts            │
│     (Node.js 模块系统加载)              │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  8. vite.config.ts 中的代码执行         │
│     - loadEnv() 读取 .env 文件          │
│     - 使用 Node.js fs 模块              │
│     - 返回配置对象                      │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  9. Vite 启动开发服务器                  │
│     - 使用配置对象                       │
│     - 启动 HTTP 服务器                  │
└─────────────────────────────────────────┘

✅ 总结

  1. npm run dev 最终执行的是 Node.js 命令

    • npmnode node_modules/.bin/unh
    • unhnode node_modules/.bin/vite
  2. 会自动读取指定文件

    • Vite 自动查找 vite.config.ts
    • 使用 Node.js 的 fs 模块读取
    • 使用 Node.js 的模块系统加载
  3. vite.config.ts 是 Node.js 模块

    • 会被 Node.js 执行
    • 可以使用所有 Node.js API
    • 在 Node.js 环境中运行
  4. 是一层封装

    • npm 封装了命令执行
    • unh 封装了 uni-app 启动流程
    • vite 封装了构建工具
    • vite.config.ts 是配置层

关键点

  • 执行环境:Node.js
  • 配置文件:Node.js 模块
  • 文件读取 :Node.js fs 模块
  • 自动查找:Vite 自动查找配置文件
  • 执行时机:每次启动时执行
相关推荐
竹秋…2 小时前
el-table 滚动条小箭头点不了且部分滚动条无法拖动的问题
javascript·vue.js·elementui
曾富贵2 小时前
【eslint】快速配置
前端
阿珊和她的猫2 小时前
Webpack Loader 和 Plugin 实现原理详解
前端·webpack·node.js
做怪小疯子2 小时前
JavaScript 中Array 整理
开发语言·前端·javascript
六元七角八分2 小时前
CSDN文章如何转出为PDF文件保存
开发语言·javascript·pdf
香香爱编程3 小时前
Electron里的electron-window-state 使用
前端·javascript·vue.js·vscode·electron·前端框架
涔溪3 小时前
Vue 中实现 PDF 文件上传
javascript·vue.js·pdf
JohnYan3 小时前
Bun技术评估 - 29 Docker集成
javascript·后端·docker
玉宇夕落3 小时前
JavaScript 执行状态全景图:从调用栈到事件循环,深入理解异步机制
javascript