create-vite 源码解析它来喽

create-vite的源码很简单,只有一个文件,代码总行数400左右,但是实际需要阅读的代码大约只有200行左右,废话不多说,直接开始吧。

代码结构

create-vite的代码结构非常简单,直接将index.ts拉到最底下,发现只执行了一个函数init()

init().catch((e) => {console.error(e)
}) 

我们的故事将从这里开始。

init()

init()函数的代码有点长,但是实际上也不复杂,我们先来看看它最开头的两行代码:

async function init() {const argTargetDir = formatTargetDir(argv._[0])const argTemplate = argv.template || argv.t
} 

首先可以看到init函数是一个异步函数,最开始的两行代码分别获取了argv._[0]argv.template或者argv.t

这个argv是怎么来的,当然是通过一个解析包来解析的,在顶部有这样的一段代码:

const argv = minimist(process.argv.slice(2), { string: ['_'] }) 

就是这个minimist包,它的作用就是解析命令行参数,感兴趣的可以自行了解,据说这个包也是百来行代码。

继续往下,这两个参数就是我们在执行create-vite命令时传入的参数,比如:

create-vite my-vite-app 

那么argv._[0]就是my-vite-app

如果我们执行的是:

create-vite my-vite-app --template vue 

那么argv.template就是vue

argv.t就是argv.template的简写,相当于:

create-vite my-vite-app --t vue

# 等价于

create-vite my-vite-app --template vue 

通过打断点的方式,可以看到结果和我们预想的一样。

formatTargetDir(argv._[0])就是格式化我们传入的目录,它会去掉目录前后的空格和最后的/,比如:

formatTargetDir(' my-vite-app ') // my-vite-app
formatTargetDir(' my-vite-app/') // my-vite-app 

这个代码很简单,就不贴出来了,继续往下:

let targetDir = argTargetDir || defaultTargetDir 

targetDir是我们最终要创建的目录,defaultTargetDir的值是vite-project,如果我们没有传将会用这个值来兜底。

紧接着后面跟着一个getProjectName的函数,通常来讲这种代码可以跳过先不看,但是这里的getProjectName函数有点特殊;

const getProjectName = () =>targetDir === '.' ? path.basename(path.resolve()) : targetDir 

它会根据targetDir的值来判断我们的项目是不是在当前目录下创建的,如果是的话,就会返回当前目录的名字,比如:

create-vite . 

可以看到如果项目名称传的是.,那么getProjectName函数就会返回当前目录的名字,也就是create-vite(根据自己的情况而定);

不看源码还真不知道这里还可以这么用,继续往下,就是定义了一个问题数组:

result = await prompts([]) 

这个prompts函数是一个交互式命令行工具,它会根据我们传入的问题数组来进行交互,就比如源码中,一共列出了6个问题:

  • projectName:项目名称
  • overwrite:是否覆盖已存在的目录
  • overwriteChecker:检测覆盖的目录是否为空
  • packageName:包名
  • framework:框架
  • variant:语言

当执行create-vite命令时,后面不跟着任何参数,而且我们一切操作都是合规的,那么只会经历三个问题:

  • projectName:项目名称
  • framework:框架
  • variant:语言

projectName:项目名称

配置项如下:

var projectName = {type: argTargetDir ? null : 'text',name: 'projectName',message: reset('Project name:'),initial: defaultTargetDir,onState: (state) => {targetDir = formatTargetDir(state.value) || defaultTargetDir}
} 

先来简单介绍一个每一个配置项的含义:

  • type:问题的类型,这里的null表示不
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值