npm run dev原理

发布于:2025-03-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

1、npm run dev会启动根目录下的package.json里的scripts字段指定的命令。

所以执行npm run dev等同于执行vite(仅限于下图场景中)

2、npm会到node_modules/.bin/目录下找到vite.sh,并执行该shell

该shell文件如下

#!/bin/sh
# $0 代表脚本自身的路径
# dirname 获取脚本所在的目录路径
# sed -e 's,\\,/,g' 将路径中的\替换为/ ,确保不同系统路径格式统一
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

# 若环境为windows,将 basedir 转换为 Windows 风格的路径
case `uname` in
    *CYGWIN*|*MINGW*|*MSYS*)
        if command -v cygpath > /dev/null 2>&1; then
            basedir=`cygpath -w "$basedir"`
        fi
    ;;
esac

# 执行"$basedir/../vite/bin/vite.js"
# "$@"表示将命令行给脚本的参数传递给 vite.js
if [ -x "$basedir/node" ]; then # 如果该路径下有node
  exec "$basedir/node"  "$basedir/../vite/bin/vite.js" "$@"
else 
  exec node  "$basedir/../vite/bin/vite.js" "$@"
fi

大致意思是,找到node_modules/vite/bin/vite.js并执行。但是做了不同系统的兼容和不同node的选择。

3、那找到该vite.js后,node会执行该文件。

#!/usr/bin/env node
import { performance } from 'node:perf_hooks'

if (!import.meta.url.includes('node_modules')) {
  try {
    // 开发环境下启用源码映射
    await import('source-map-support').then((r) => r.default.install())
  } catch (e) { }
}
// 将当前时间(ms)存储在全局变量里,便于后续性能分析
global.__vite_start_time = performance.now()


// debugIndex:  查找是否存在 -d 或 --debug 参数,用于启用调试模式
// filterIndex: 查找是否存在 -f 或--filter 参数,用于过滤调试日志
// profileIndex:查找是否存在--profile 参数,用于性能分析
const debugIndex = process.argv.findIndex((arg) => /^(?:-d|--debug)$/.test(arg))
const filterIndex = process.argv.findIndex((arg) =>
  /^(?:-f|--filter)$/.test(arg),
)
const profileIndex = process.argv.indexOf('--profile')

// 如果存在 -d 或 --debug 参数,提取其值(如 vite:*),并将其添加到 DEBUG 环境变量中。
// DEBUG 是一个常用的环境变量,用于控制调试日志的输出。
if (debugIndex > 0) {
  let value = process.argv[debugIndex + 1]
  if (!value || value.startsWith('-')) {
    value = 'vite:*'
  } else {
    // support debugging multiple flags with comma-separated list
    value = value
      .split(',')
      .map((v) => `vite:${v}`)
      .join(',')
  }
  process.env.DEBUG = `${process.env.DEBUG ? process.env.DEBUG + ',' : ''
    }${value}`
  // 如果存在 -f 或 --filter 参数,提取其值并存储在 VITE_DEBUG_FILTER 环境变量中,用于进一步过滤调试日志。
  if (filterIndex > 0) {
    const filter = process.argv[filterIndex + 1]
    if (filter && !filter.startsWith('-')) {
      process.env.VITE_DEBUG_FILTER = filter
    }
  }
}

// 动态导入 Vite 的 CLI 入口文件,vite核心所在
function start() {
  return import('../dist/node/cli.js')
}

// 启用性能分析
if (profileIndex > 0) {
  process.argv.splice(profileIndex, 1)
  const next = process.argv[profileIndex]
  if (next && !next.startsWith('-')) {
    process.argv.splice(profileIndex, 1)
  }
  const inspector = await import('node:inspector').then((r) => r.default)
  const session = (global.__vite_profile_session = new inspector.Session())
  session.connect()
  session.post('Profiler.enable', () => {
    session.post('Profiler.start', start)
  })
} else {
  start()
}

所以,npm run dev = node .\node_modules\vite\bin\vite.js

问题:既然npm run dev等于执行vite,为什么控制台执行vite会报错?

答:因为vite没有在系统环境变量里。当将node_modules/.bin/ 添加到 PATH就可以成功执行;或者全局安装vite。

所以就是,npm run dev ---> vite ---> /node_modules/.bin/vite ---> vite.js ---> cli.js(vite核心)

绕这么大一圈,是为了不同系统的兼容、固定的命令(便于开发者)、支持非全局vite(版本隔离)!


网站公告

今日签到

点亮在社区的每一天
去签到