学习 create-vite 源码后,感觉真不一样

1,247 阅读3分钟

我正在参与掘金会员专属活动-源码共读第一期,点击参与

前言

已经学习了一段时间的源码了,在写源码 demo 小例子的时候都是使用 react 项目作为模板,而我的 react 项目正好是由create-vite来创建的,因此,今天来学习一下关于create-vite的源码。话不多说,咱们直接开始学习。

创建 vite 项目

Vite 是一种新型的前端构建工具,能够显著提升前端开发体验。整个create-vite的源码不多,代码总行数400左右。首先我先用npm init vite命令创建了一个空项目,文件结构如下所示。

image.png

运行项目通过npm run dev命令,可以看出它启动项目是非常快的。一个vite创建的项目就运行起来了。

image.png

源码解读

源码四百来行,这里就不附上源码部分了,可以自行去 index.ts 文件下查看。下面附上关键部分的引入包。

image.png

我们进入 github 部分,首先来看看 package.json 文件吧,可以看到装了哪些依赖。

image.png

cross-spawnnode spawn 和 spawnSync的跨平台实现,kolorist是一个可以让命令行输出带有色彩的工具,在我们初始化项目选择框架的时候,那里的色彩就是通过它来实现的(如下图所示)。minimist是一个命令行参数解析工具。prompt,顾名思义,就是提示的意思,在我们输入东西的时候给出相应提示。我们接下来重点看看minimistprompt

image.png

minimist

const argv = minimist<{
    t?: string
    template?: string
}>(process.argv.slice(2), { string: ['_'] })

从代码可以看出,这里调用了process对象的属性。通过process.argv属性会返回一个数组,即命令行参数的字符串数组。process对象是一个全局变量,不需要引入,可以直接使用。

prompt

let result = {}
try {
    result = await prompts(
      [
        {
          type: targetDir ? null : 'text',
          name: 'projectName',
          message: reset('Project name:'),
          initial: defaultTargetDir,
          onState: (state) => {
            targetDir = formatTargetDir(state.value) || defaultTargetDir
          }
        }
        .....
} catch (cancelled) {
    console.log(cancelled.message)
    return
}
const { framework, overwrite, packageName, variant } = result

prompt在这里主要做了什么呢?代码比较长,但是可以抓住关键词代码,比如代码中的 name: 'projectName',以及结合它的作用我们可以发现,它就是在一步一步引导我们往下进行相应的步骤。这就是prompt在这里发挥的作用。

package.json

最后来看看package.json文件是如何写入的。

const files = fs.readdirSync(templateDir)
for (const file of files.filter((f) => f !== 'package.json')) {
    write(file)
}
const pkg = JSON.parse(
    fs.readFileSync(path.join(templateDir, `package.json`), 'utf-8')
)
pkg.name = packageName || getProjectName()

write('package.json', JSON.stringify(pkg, null, 2))

总结

简单地看完一遍源码,能清晰地发现我们平时初始化项目的步骤通过代码一步步展现出来。 minimist是用来解析命令行参数,prompts是用来提示用户输入,nodefs模块是用来创建项目。安装的每一个依赖或者每一步步骤都是有它的逻辑的。或许是经常使用vite创建项目的缘故,整个代码看下来还是比较轻松的,只不过可能对它里面更深层次的东西没有把握住,对于源码中其他更细节的部分,还会继续研究,将它更进一步地吃透。