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 的工作:
- 读取
unh.config.ts配置文件(Node.js 模块) - 解析平台参数(如
wx→mp-weixin) - 执行 hooks(如
devhook) - 调用 Vite CLI
3. Vite CLI(Node.js 可执行文件)
bash
# unh 内部会调用:
vite dev
# 或
npx vite dev
Vite 的工作:
- 读取
vite.config.ts配置文件(Node.js 模块) - 加载环境变量(
.env文件) - 启动开发服务器
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)
查找顺序:
- 项目根目录
- 使用
fs模块读取文件 - 使用 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
执行过程:
-
npm 解析命令
bash# npm 内部执行: node node_modules/.bin/unh dev -
unh 启动
javascript// unh 内部代码(简化) const config = require('./unh.config.ts') config.hooks.dev('h5', {}) -
unh 调用 Vite
bash# unh 内部执行: node node_modules/.bin/vite dev -
Vite 读取配置
javascript// Vite 内部代码(简化) const config = require('./vite.config.ts') const resolvedConfig = config.default({ mode: 'development' }) -
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
执行过程:
-
设置环境变量
bash# Shell 设置环境变量 process.env.VITE_MODE = 'test' -
npm 执行命令
bash# npm 继承环境变量 node node_modules/.bin/unh dev -
vite.config.ts 读取环境变量
typescriptexport 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 服务器 │
└─────────────────────────────────────────┘
✅ 总结
-
✅ npm run dev 最终执行的是 Node.js 命令
npm→node node_modules/.bin/unhunh→node node_modules/.bin/vite
-
✅ 会自动读取指定文件
- Vite 自动查找
vite.config.ts - 使用 Node.js 的
fs模块读取 - 使用 Node.js 的模块系统加载
- Vite 自动查找
-
✅ vite.config.ts 是 Node.js 模块
- 会被 Node.js 执行
- 可以使用所有 Node.js API
- 在 Node.js 环境中运行
-
✅ 是一层封装
npm封装了命令执行unh封装了 uni-app 启动流程vite封装了构建工具vite.config.ts是配置层
关键点
- 执行环境:Node.js
- 配置文件:Node.js 模块
- 文件读取 :Node.js
fs模块 - 自动查找:Vite 自动查找配置文件
- 执行时机:每次启动时执行