npm run dev 用 vite 启动是怎么做到的

在我们执行这个命令的时候会去找 package.jsonscripts 然后执行对应的 dev 命令

Untitled

那为什么我们不直接执行 vite 命令不是更方便吗

因为在我们的电脑上面并没有配置过相关命令 所以无法直接执行

Untitled

其实在我们执行 npm install 的时候(包含 vite) 会在 node_modules/.bin/ 创建好可执行文件

而当执行 npm run dev 的时候,npm 会去项目的 package.json 文件里找 scripts 里找对应的 dev 指令执行。

执行 vite 的时候,npm 会找到 ./node_modules/.bin 对应的 vite 脚本(.bin中的文件在npm安装对应依赖的时候创建)。下面是 vite 脚本。可以看到文件顶部写着 #!/user/bin/env node ,表示这是一个通过使用 Node 执行的脚本。

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

if (!import.meta.url.includes('node_modules')) {
  try {
    // only available as dev dependency
    await import('source-map-support').then((r) => r.default.install())
  } catch (e) {}
}

global.__vite_start_time = performance.now()

// check debug mode first before requiring the CLI.
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')

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}`

  if (filterIndex > 0) {
    const filter = process.argv[filterIndex + 1]
    if (filter && !filter.startsWith('-')) {
      process.env.VITE_DEBUG_FILTER = filter
    }
  }
}

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 在安装依赖的时候会自动创建该文件呢?我们可以找到 vite 的依赖包,打开来看一下,可以看到,在 vitepackage.json 里面有如下配置:

"bin": {
  "vite": "bin/vite.js"
},

npm 读取到该配置时,会将对应的文件链接到 .bin 文件目录下

Untitled

接下来,我们回到 vite.js 文件,我们找到下面这个方法,找到对应的执行文件。

function start() {
  require('../dist/node/cli')
}

来看一下它的核心代码:

const cac = (name = "") => new CAC(name);
const cli = cac('vite');

而这个 cli.js 就是真正 vite 执行的 js 代码了。