本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。这是源码共读的第37期,链接: juejin.cn/post/712908… 。
我们使用vite初始化项目的时候,首先在命令行中输入相应的命令,然后进行简单的交互,过一会儿一个项目就建好了。您是否了解这背后的原理呢?阅读本文一起学习吧!
1.准备工作
首先clone vite的代码:
git clone https://github.com/vitejs/vite.git
然后在packages中找到create-vite
2.源码解读
2.1 确定入口文件
读源码第一步是找到入口文件, 根据package.json的bin选项可以知道执行create-vite命令时会执行index.js文件,所以index.js文件就是入口文件。
2.2 create-vite 执行流程
index.js文件的源码行数不到400,整体逻辑清晰易懂,这里只总结了其执行流程和一些关键代码供参考。如果您想详细了解对其源码的分析可以阅读本文最后的参考资料。
可以结合下图来理解上面的流程:
2.3 create-vite关键代码
2.3.1 copy拷贝文件到目录
function copy(src, dest) {
const stat = fs.statSync(src)
if (stat.isDirectory()) {
copyDir(src, dest)
} else {
fs.copyFileSync(src, dest)
}
}
fs.statSync获取文件信息,然后判断是文件还是目录。如果是目录则使用copyDir拷贝目录中的文件;如果是文件则使用fs.copyFileSync方法拷贝文件。
2.3.2 copyDir源目录文件拷贝到目标目录
function copyDir(srcDir, destDir) {
fs.mkdirSync(destDir, { recursive: true })
for (const file of fs.readdirSync(srcDir)) {
const srcFile = path.resolve(srcDir, file)
const destFile = path.resolve(destDir, file)
copy(srcFile, destFile)
}
}
目标目录不一定存在,所以要新建目录。然后针对源目录的每个文件都要使用path.resolve计算其路径,同理计算目标文件的路径,然后调用copy方法。
2.3.3 isEmpty判断文件夹是否为空文件夹
function isEmpty(path) {
const files = fs.readdirSync(path)
return files.length === 0 || (files.length === 1 && files[0] === '.git')
}
使用fs.readdirSync读取文件夹,返回值为文件数组,数组长度为0或者长度为1但是只有.git文件,那么这个文件夹可以认为是空文件夹。
2.3.4 emptyDir将文件夹清空
function emptyDir(dir) {
if (!fs.existsSync(dir)) {
return
}
for (const file of fs.readdirSync(dir)) {
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true })
}
}
如果目录不存在则返回,否则循环遍历目录中的每一个文件或者目录进行递归强制删除。
3.总结
create-vite 中对于命令参数解析用到了命令行解析工具minimist;和使用者交互确定项目名称和类型用到了交互式命令行提示工具prompts;为了使命令行输出信息更加美观醒目则使用了kolorist这款命令行颜色工具。
create-vite涉及到了大量的文件相关操作,例如文件的读写以及文件夹的创建和删除,这些功能的实现则借助了node.js fs 模块相关的API; 另外涉及到文件的路径的确定则使用到了path模块和url模块的API。
三方npm包
Node API
4.收获
第一,了解使用vite创建项目的原理;
第二,学习到node.js重要API的使用方法;
第三,积累了有用的npm包。
参考资料