vite源码之配置文件
前言
配置文件在前端是非常常见的,如 webpack/rollup 等打包工具,又或者是 babel/postcss/ts 等编译工具都有自己的配置文件。它们有的是js文件、有的是json文件。而vite作为新一代的前端工具,打包的效率与开发环境的体验自不必说,它在配置文件这个领域也与之前的工具有所区别的。
vite配置文件的优点
-
可以使用ts编写
vite的配置文件兼容了多种格式,如:
js
mjs
cjs
ts
mts
cts
等,比较常用的就是js
与ts
了,并且即使你的项目并没有安装typescript
,vite配置文件依旧是可以使用ts文件,那这是如何做到的呢?我们后面再做分析。 -
使用 defineConfig 来得到类型提示
当配置非常多,同时配置属性名比较长时,能够得到类型提示的优势就非常大了。类型提示能够使你不必每次都去查阅官方文档,同时也避免了你在书写过程中把配置写错的尴尬。
vite对ts配置文件的处理
对于配置文件的读取其实很简单了,使用 await import
或者 require
即可。但是如何处理ts配置文件呢?await import
或者 require
都是仅支持js文件的。我读了一下vite的源码,是通过esbuild将ts代码编译成功js后再输出到一个临时文件中,最后通过 dynamicImport
去读取的,代码大概如下:
async function resolveConfigFiles(configFiles: string[]) {
// 获取配置文件的完整路径
const configFilePath = await getConfigFilePath(configFiles)
if (!configFilePath) {
render.noConfigurationProvide()
return
}
const buildResult = await build({
entryPoints: [configFilePath],
bundle: true,
platform: 'node',
target: ['node14', 'node16'],
format: await getModuleFormat(configFilePath), // 获取文件是 esm 还是 cjs
outfile: 'out.js',
write: false, // 设置为false时buildResult才会有outputFiles
loader: {
'.ts': 'ts' // 处理ts文件
}
})
const code = buildResult.outputFiles?.[0]?.text || ''
try {
await access(TMP_PATH)
} catch(e) {
await mkdir(TMP_PATH)
}
// 将编译成功js的配置文件写入到临时的文件中
await writeFile(
join(TMP_PATH, TMP_CONFIG_FILE),
code,
'utf8'
)
// 通过dynamicImport去解析配置,最后得到具体配置对象
const mod = await import(`file://${join(TMP_PATH, TMP_CONFIG_FILE)}`)
return mod.default.default
}
以上代码并非vite源码,而是我读了vite源码之后用在了自己写的工具中,vite的大致核心逻辑其实也是这样的。
如何获得类型提示
获得类型提示的关键就是 defineConfig
函数,而该函数本身是没有逻辑的,只是将输入的配置再return出去。代码如下:
export function defineConfig(config: UserConfiguration): UserConfiguration {
return config;
}
主要是利用了函数来得到类型提示,而通过 dynamicImport
之后的结果其实是函数的运行结果,也就是传入的配置。
结语
vite作为新一代的前端工具,虽然现在还不如 webpack/rollup 这些工具成熟。但其优势也非常明显,打包速度有了esbuild的加持就不必多说了,它在很多细节的处理上也让人焕然一新,期待它慢慢的成长吧!
转载自:https://juejin.cn/post/7156241791830261768