Vite 源码了解
本次源码学习基于 vite 2.9.6 版本
clone 项目
https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md
The Vite repo is a monorepo using pnpm workspaces. The package manager used to install and link dependencies must be pnpm.
vite 源码 clone 到本地后,需要使用 pnpm 安装依赖
To develop and test the core vite package:
-
Run
pnpm i
in Vite's root folder -
Run pnpm
run build
in Vite's root folder. -
If you are developing Vite itself, you can go to packages/vite and run
pnpm run dev
to automatically rebuild Vite whenever you change its code.
启动 playground
pnpm i
pnpm run build
# 选择一个测试项目
cd packages\playground\vue
pnpm vue
包目录结构
在 vite 源码的 packages 目录下主要有以下目录:
├── create-vite -- 用于创建新的 Vite 项目
├── playground -- demo及测试用例
├── plugin-legacy -- 官方插件,提供兼容支持
├── plugin-react -- 官方插件,支持React
├── plugin-vue -- 官方插件,支持Vue
├── plugin-vue-jsx -- 官方插件,支持Vue3 JSX
└── vite -- Vite核心包
Command Line Interface
{
"scripts": {
"dev": "vite", // start dev server, aliases: `vite dev`, `vite serve`
"build": "vite build", // build for production
"preview": "vite preview" // locally preview production build
}
}
vite dev
在playground中运行 npm run dev
命令,即运行 vite dev
命令
实际执行的脚本是:
packages\vite\src\node\cli.ts
源码
// dev
cli
.command('[root]', 'start dev server') // default command
.alias('serve') // the command is called 'serve' in Vite's API
.alias('dev') // alias to align with the script name
.option('--host [host]', `[string] specify hostname`)
.option('--port <port>', `[number] specify port`)
.option('--https', `[boolean] use TLS + HTTP/2`)
.option('--open [path]', `[boolean | string] open browser on startup`)
.option('--cors', `[boolean] enable CORS`)
.option('--strictPort', `[boolean] exit if specified port is already in use`)
.option(
'--force',
`[boolean] force the optimizer to ignore the cache and re-bundle`
)
.action(async (root: string, options: ServerOptions & GlobalCLIOptions) => {
// output structure is preserved even after bundling so require()
// is ok here
const { createServer } = await import('./server')
try {
const server = await createServer({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
server: cleanOptions(options)
})
if (!server.httpServer) {
throw new Error('HTTP server not available')
}
await server.listen()
const info = server.config.logger.info
info(
colors.cyan(`\n vite v${require('vite/package.json').version}`) +
colors.green(` dev server running at:\n`),
{
clear: !server.config.logger.hasWarned
}
)
server.printUrls()
// @ts-ignore
if (global.__vite_start_time) {
// @ts-ignore
const startupDuration = performance.now() - global.__vite_start_time
info(
`\n ${colors.cyan(`ready in ${Math.ceil(startupDuration)}ms.`)}\n`
)
}
} catch (e) {
createLogger(options.logLevel).error(
colors.red(`error when starting dev server:\n${e.stack}`),
{ error: e }
)
process.exit(1)
}
})
当执行vite dev
不带任何参数时,
root 为 undefined, options为 { '--': [] }, 即:
const server = await createServer({
root: undefined,
base: undefined,
mode: undefined,
configFile: undefined,
logLevel: undefined,
clearScreen: undefined,
server: undefined,
});
await server.listen();
<h1 data-line="0" id="Vite 源码了解">Vite 源码了解</h1>
<p data-line="2"><strong>本次源码学习基于 vite 2.9.6 版本</strong></p>
<h2 data-line="4" id="clone 项目">clone 项目</h2>
<blockquote data-line="6">
<p>https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md<br>
The Vite repo is a monorepo using pnpm workspaces. The package manager used to install and link dependencies must be pnpm.</p>
</blockquote>
<p data-line="9">vite 源码 clone 到本地后,需要使用 pnpm 安装依赖</p>
<p data-line="11">To develop and test the core vite package:</p>
<ul data-line="13">
<li>
<p>Run <code>pnpm i</code> in Vite's root folder</p>
</li>
<li>
<p>Run pnpm <code>run build</code> in Vite's root folder.</p>
</li>
<li>
<p>If you are developing Vite itself, you can go to packages/vite and run <code>pnpm run dev</code> to automatically rebuild Vite whenever you change its code.</p>
</li>
</ul>
<h2 data-line="19" id="启动 playground">启动 playground</h2>
<pre data-line="21"><code class="language-shell" language=shell><span class="code-block">pnpm i
pnpm run build
# 选择一个测试项目
cd packages\playground\vue
pnpm vue</span></code></pre>
<h2 data-line="29" id="包目录结构">包目录结构</h2>
<p data-line="31"><strong>在 vite 源码的 packages 目录下主要有以下目录:</strong></p>
<pre data-line="33"><code class="language-shell" language=shell><span class="code-block">├── create-vite -- 用于创建新的 Vite 项目
├── playground -- demo及测试用例
├── plugin-legacy -- 官方插件,提供兼容支持
├── plugin-react -- 官方插件,支持React
├── plugin-vue -- 官方插件,支持Vue
├── plugin-vue-jsx -- 官方插件,支持Vue3 JSX
└── vite -- Vite核心包</span></code></pre>
<h2 data-line="43" id="Command Line Interface">Command Line Interface</h2>
<pre data-line="45"><code class="language-javascript" language=javascript><span class="code-block">{
"scripts": {
"dev": "vite", // start dev server, aliases: `vite dev`, `vite serve`
"build": "vite build", // build for production
"preview": "vite preview" // locally preview production build
}
}</span></code></pre>
<h2 data-line="55" id="vite dev">vite dev</h2>
<p data-line="56">在playground中运行 <code>npm run dev</code> 命令,即运行 <code>vite dev</code> 命令<br>
实际执行的脚本是:</p>
<pre data-line="58"><code class="language-shell" language=shell><span class="code-block">packages\vite\src\node\cli.ts</span></code></pre>
<p data-line="61">源码</p>
<pre data-line="62"><code class="language-typescript" language=typescript><span class="code-block">// dev
cli
.command('[root]', 'start dev server') // default command
.alias('serve') // the command is called 'serve' in Vite's API
.alias('dev') // alias to align with the script name
.option('--host [host]', `[string] specify hostname`)
.option('--port <port>', `[number] specify port`)
.option('--https', `[boolean] use TLS + HTTP/2`)
.option('--open [path]', `[boolean | string] open browser on startup`)
.option('--cors', `[boolean] enable CORS`)
.option('--strictPort', `[boolean] exit if specified port is already in use`)
.option(
'--force',
`[boolean] force the optimizer to ignore the cache and re-bundle`
)
.action(async (root: string, options: ServerOptions & GlobalCLIOptions) => {
// output structure is preserved even after bundling so require()
// is ok here
const { createServer } = await import('./server')
try {
const server = await createServer({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
server: cleanOptions(options)
})
if (!server.httpServer) {
throw new Error('HTTP server not available')
}
await server.listen()
const info = server.config.logger.info
info(
colors.cyan(`\n vite v${require('vite/package.json').version}`) +
colors.green(` dev server running at:\n`),
{
clear: !server.config.logger.hasWarned
}
)
server.printUrls()
// @ts-ignore
if (global.__vite_start_time) {
// @ts-ignore
const startupDuration = performance.now() - global.__vite_start_time
info(
`\n ${colors.cyan(`ready in ${Math.ceil(startupDuration)}ms.`)}\n`
)
}
} catch (e) {
createLogger(options.logLevel).error(
colors.red(`error when starting dev server:\n${e.stack}`),
{ error: e }
)
process.exit(1)
}
})</span></code></pre>
<p data-line="128">当执行<code>vite dev</code> 不带任何参数时,<br>
root 为 undefined, options为 { '--': [] }, 即:</p>
<pre data-line="130"><code class="language-typescript" language=typescript><span class="code-block"> const server = await createServer({
root: undefined,
base: undefined,
mode: undefined,
configFile: undefined,
logLevel: undefined,
clearScreen: undefined,
server: undefined,
});
await server.listen();</span></code></pre>