Vite源码分析
为了更好的在工作中使用Vite,分析Vite源码,了解Vite的运行流程。 另外,通过源码学习,了解Vite中用的一些框架。扩展自己的知识面。 和大家分享我的学习成果,如果有什么问题?请大家及时纠正。
Vite 目录结构和构建
从Github上下载Vite 3.1.0的最新代码。
安装pnpm
安装命令参照官网:pnpm官网
curl -fsSL https://get.pnpm.io/install.sh | sh -
进入项目根目录安装依赖
pnpm install
workspace package 理解
打开pnpm-workspace.yaml文件,可以看到下面的代码。pnpm-workspace说明
packages:
- 'packages/*'
- 'playground/**'
简单的说,配置了pnpm-workspace以后,项目的安装包可以引入workspace文件夹里面的js文件。可以看到,我们可以安装packages和playground里面的程序。
// package.json
"devDependencies": {
"vite": "workspace:*"
},
vite 目录理解
vite目录结构如下:
client和node是源码存放的目录,不能直接使用,需要编译后才能运行。bin目录里的vite.js是程序的入口,可以看到调用的是编译后的cli.js。
// 从vite.js里面找到程序入口
function start() {
return import('../dist/node/cli.js')
}
types文件夹里面,放的是各种type定义文件
打包编译Vite
打开Vite文件夹下的package.json,配置如下:
"scripts": {
"dev": "rimraf dist && pnpm run build-bundle -w",
"build": "rimraf dist && run-s build-bundle build-types",
"build-bundle": "rollup --config rollup.config.ts --configPlugin typescript",
"build-types": "run-s build-temp-types patch-types roll-types check-dist-types",
"build-temp-types": "tsc --emitDeclarationOnly --outDir temp/node -p src/node",
"patch-types": "tsx scripts/patchTypes.ts",
"roll-types": "api-extractor run && rimraf temp",
"check-dist-types": "tsc --project tsconfig.check.json",
"lint": "eslint --cache --ext .ts src/**",
"format": "prettier --write --cache --parser typescript \"src/**/*.ts\"",
"prepublishOnly": "npm run build"
},
可以看到build-bundle主要是通过rollup进行代码编译打包的,所以打开rollup.config.ts查看各种入口文件:
// env输入文件是env.ts
const envConfig = defineConfig({
input: path.resolve(__dirname, 'src/client/env.ts'),
plugins: [
typescript({
tsconfig: path.resolve(__dirname, 'src/client/tsconfig.json')
})
],
output: {
file: path.resolve(__dirname, 'dist/client', 'env.mjs'),
sourcemap: true
}
})
// client输入文件是client.ts
const clientConfig = defineConfig({
input: path.resolve(__dirname, 'src/client/client.ts'),
external: ['./env', '@vite/env'],
plugins: [
typescript({
tsconfig: path.resolve(__dirname, 'src/client/tsconfig.json')
})
],
output: {
file: path.resolve(__dirname, 'dist/client', 'client.mjs'),
sourcemap: true
}
})
// nodeConfig的输入文件有index.ts(各种types定义) cli.ts(核心程序) contants.ts(各种常量)
function createNodeConfig(isProduction: boolean) {
return defineConfig({
...sharedNodeOptions,
input: {
index: path.resolve(__dirname, 'src/node/index.ts'),
cli: path.resolve(__dirname, 'src/node/cli.ts'),
constants: path.resolve(__dirname, 'src/node/constants.ts')
},
output: {
...sharedNodeOptions.output,
sourcemap: !isProduction
},
external: [
'fsevents',
...Object.keys(pkg.dependencies),
...(isProduction ? [] : Object.keys(pkg.devDependencies))
],
plugins: createNodePlugins(
isProduction,
!isProduction,
// in production we use api-extractor for dts generation
// in development we need to rely on the rollup ts plugin
isProduction ? false : path.resolve(__dirname, 'dist/node')
)
})
}
进入vite文件夹根目录,运行npm run build进行打包,生成dist文件夹以及里面的js文件。
Tips小知识
通过rollup和api-extractor,可以把所有的typescript定义文件都集中生成在一个index.d.ts文件里面。
api-extractor相关知识