最近很多朋友都遇到了西瓜霜治口腔溃疡原理的问题,今天小编就来为大家解答,快来看看吧。问题描述:本人口腔溃疡,医生开了西瓜霜喷雾。什么是西瓜霜治口腔溃疡原理? 病情分析:西瓜霜治口腔溃疡原理是杀菌,促进血液循环。西瓜
2024-01-16 08:24:01
大家好,我是鄂茶哥。
你通常会很开心。npm create vite@lastest初始化一个vite项目。
那么你知道它的原理是什么吗?
今天这篇文章就带领大家一起学习它的原理,源代码不到400行。
2. npm init && npm createNpm初始化文档[4]已写入。Create实际上是init的别名。
也就是说,npm create vite@lastest相当于= >;Npx create-vite@lastest,latest是版本号,可以通过以下命令查看最新版本。
NPM dist-tag ls create-vite # output #最新版本:3.0.0
然后我们克隆vite项目,调试包/create-vite,分析它的源代码实现。
3. 克隆项目 && 调试源码正如我在上一篇文章中所写的,新手程序员必须学习的基本技能——调试JS代码,这里就不赘述了。
可以直接克隆我的项目调试。同时,请欢迎明星。看开源项目,一般先看README.md[5]和对应的CONTRIBUTING.md[6]。
git clone https://github.com/lxchuan12/vite-analysis.gitcd vite-analysis/vite 2 # NPM I-g pnpmpnpm install # At this index . js文件断点#调试节点vite 2/packages/create-vite/index . js在命令行终端。
贡献文档[7]还详细介绍了如何调试[8]。
调试截图:
调试截图
控制台输出:
控制台输出
最终生成的文件:
顺便问一下,我如何保存vite记录?其实我用的是git子树。
#创建git子树add-prefix = vite 2 https://github.com/vitejs/vite.git Main #更新git子树pull-prefix = vite 2 https://github.com/vitejs/vite.git Main
找到路径,packages/create-vite看看package.json。
{ "姓名& # 34;: "创建-邀请& # 34;, "版本& # 34;: "3.0.0", "类型& # 34;: "模块& # 34;, "斌& # 34;: { "创建-邀请& # 34;: "index.js & # 34, "cva & # 34: "index.js & # 34}, "main & # 34: "index.js & # 34, "引擎& # 34;: { "节点& # 34;: "^14.18.0 | | >;=16.0.0"},}
型号指定模块是指ES模块。bin可执行命令是create-vite或别名cva。我们可以知道主文件index.js代码限制了Nodejs的更高版本。
然后我们进行调试以查看这个index.js文件。
4. 主流程 init 函数拆分//高级版本的节点支持,节点前缀从& # 39;节点:fs & # 39导入路径来自& # 39;节点:路径& # 39;从& # 39;导入{ fileURLToPath };节点:url & # 39//解析命令行的参数链接:https://npm.im/minimistimport minimit from & # 39;最小化& # 39;//求一个这样的链接:https://npm.im/promptsimport提示来自& # 39;提示& # 39;//终端色彩输出的库链接:https://npm.im/koloristimport {蓝色、青色、绿色、浅红色、品红色、红色、复位、黄色} from & # 39kolorist & # 39//通过定义与选项(_)关联的参数// non需要被解析为字符串,避免自动转换为项目名称的数字。请参阅# 4606 const argv = minimat(process . argv . slice(2),{ string:[& # 39;_']})//当前Nodejs执行目录const cwd = process.cwd()//省略主函数内容,异步函数init () {} init()。catch ((e) = > { console.error(e)})
4.1 输出的目标路径//命令行的第一个参数,而不是反斜杠/是空字符串Lettargetdir = Format Targetdir(argv。_[0])//命令行参数-template or-tlettemplate = argv . template | | argv . t const默认Targetdir = & # 39vite-project & # 39;//获取项目名称const Get project name =()= & gt;targetDir = = = & # 39。'?path . basename(path . resolve()):targetDir
4.1.1 延伸函数 formatTargetDir将反斜杠/替换为空字符串。
函数格式targetDir(targetDir){ return targetDir?。修剪()。替换(/\/ $/g,& # 39;')}
4.2 prompts 询问项目名、选择框架,选择框架变体等提示[9]根据用户的输入和选择,代码已被删除。
let result = { } try { result = await prompts([{ type:targetDir?null:& # 39;正文& # 39;,姓名:& # 39;projectName & # 39,消息:重置(& # 39;项目名称:& # 39;),initial: defaultTargetDir,onState:(state)= & gt;{ Targetdir = Format Targetdir(state。value) || DefaultTargetdir}},//省略一些],{ on cancel:()= & gt;{抛出新错误(红色(& # 39;✖') '操作被取消& # 39;)} } } } Catch(cancelled){ console . log(cancelled . message)return }//与提示关联的用户选择//框架framework //覆盖现有目录。是否要重写// packageName输入的项目名// variant,如react = & gtreact-tsconst { framework,overwrite,packageName,variant } = result
4.3 重写已有目录/或者创建不存在的目录//与提示关联的用户选择const {framework,overwrite,packagename,variant } = result//directory const root = path . join(CWD,targetdir)if(overwrite){//Delete folder empty dir(root)} else if(!fs . exist sync(root)){//新文件夹fs.mkdirsync (root,{recursive: true})}
4.3.1 延伸函数 emptyDir递归删除文件夹,相当于rm -rf xxx。
函数emptyDir(dir) { if(!fs . exists sync(dir)){ return } for(fs . readdirsync(dir)的const文件){ fs.rmSync(path.resolve(dir,file),{ recursive: true,force: true }) }}
4.4 获取模板路径有这些模板目录。
从模板可以看出,目前还是比较简单的。例如,没有配置eslint appellister。如果你想为多个vite项目工作,自动添加eslint更漂亮。这里推荐Vite-pretty-lint[10],我为这个库写的源码是在第35期看的[11],也有别人写的关于如何一键自动添加eslint和pretty的支持到前端项目的好文章[12]。
//determine template template = variant | | framework | | template console . log(` \ nscafolding project in $ { root }...`)const templateDir = path . resolve(fileURLToPath(import . meta . URL),& # 39;..',` template-${template} `)
4.5 写入文件函数const write =(文件,内容)= & gt{//rename file const target path = rename files[file]?path.join(root,rename files[file]):path . join(root,file)if(content){ fs . writefilesync(target path,content)} else { copy(path . join(templateDir,file),targetPath) }}
重命名文件是因为。某些编辑器或计算机不支持gitignore。
const rename files = { _ git ignore:& # 39;。gitignore & # 39}
4.5.1 延伸函数 copy && copyDir如果是文件夹,用copyDir复制
函数copy(src,dest){ const stat = fs . statsync(src)if(stat . is directory()){ copy dir(src,dest) } else { fs.copyFileSync(src,dest)} }/* * * * @ param { string } srcDir * @ param { string } destDir */函数copyDir(srcDir,destDir) { fs.mkdirSync(destDir,{ recursive:true })for(fs . readdirsync的const文件(srcDir
4.6 根据模板路径的文件写入目标路径package.json文件是单独处理的。它的名称是输入的packageName或get。
const files = fs . readdirsync(templateDir)for(const file of files . filter((f)= & gt;f!== 'package.json & # 39)){ write(file)} const pkg = JSON . parse(fs . read file sync(path . join(templateDir,' package.json `),& # 39;utf-8 & # 39;))pkg . name = package name | | get project name()write(& # 39;package.json & # 39,JSON.stringify(pkg,null,2))
4.7 打印安装完成后的信息const pkgInfo = pkgFromUserAgent(process . env . NPM _ config _ user _ agent)const pkg manager = pkgInfo?pkginfo . name:& # 39;npm & # 39console.log(`\nDone。现在运行:\n`)if (root!= = CWD){ console . log(` CD $ { path . relative(CWD,root)} `)} switch(pkg manager){ case & # 39;纱& # 39;:console . log(& # 39;纱& # 39;)console . log(& # 39;纱线开发& # 39;)break default:console . log(` ${ pkg manager } install `)console . log(` ${ pkg manager } run dev `)break } console . log()
4.7.1 延伸的 pkgFromUserAgent 函数/* * * * @ param { string | undefined } user agent process . env . NPM _ config _ user _ agent * @ returns object | undefined */function pkgFromUserAgent(user agent){ if(!userAgent)返回未定义的const pkg spec = user agent . split(& # 39;')[0]const pkgSpecArr = pkgspec . split(& # 39;/')返回{ name: pkgSpecArr[0],version: pkgSpecArr[1] }}
第一个pkgFromUserAgent函数是从使用的包管理器创建一个项目,然后输出相应的命令npm/yarn/pnpm。
npm创建vite@lastestyarn创建vitepnpm创建vite
5. 总结让我们回顾一下控制台输出:
控制台输出
至此,我们已经分析了整个过程。代码行总数不多,不到400行。
{ "姓名& # 34;: "创建-邀请& # 34;, "版本& # 34;: "3.0.0", "类型& # 34;: "模块& # 34;, "引擎& # 34;: { "节点& # 34;: "^14.18.0 | | >;=16.0.0"}}
从package.json可以看出,代码限制了Nodejs的更高版本,使用es模块,目前不涉及打包编译。
为了保证轻量和速度,源代码中很多函数都是自己写的。比如查项目名,有著名的validate-npm-package-name[13],在vue-cli和create-react-app中都用到。比如删除文件和文件夹也是自己实现的。
依赖包很少。只靠三包。分析命令行参数minimast [14],询问选择等提示[15],终端颜色输出的库kolorist[16]
本文不涉及测试用例,有兴趣的伙伴可以看看。路径:vite/packages/create-vite/_ _ tests _ _/CLI . spec . ts[17],采用vitest[18]。
看完这篇文章,你会发现每天都要用npm create vite来初始化vite项目,create-vite只有不到400行的源代码。
我们也可以根据公司相关业务开发自己的脚手架工具。
如果觉得vite项目模板不够用,也可以自己修改添加。例如,库vite-pretty-lint[19]一键自动为多个vite项目添加eslint和pretty。
有时候我们很容易被局限在公司的项目里,从来不看开源世界,开源项目的源代码就在那里。如果我们真的愿意学习,我们可以学到很多东西。
很多源码并没有我们想象的那么深奥。源代码不应该是我们的障碍,而是我们的导师。这也可以说是我继续组织源代码阅读活动的原因之一。
,相关文章
最近很多朋友都遇到了西瓜霜治口腔溃疡原理的问题,今天小编就来为大家解答,快来看看吧。问题描述:本人口腔溃疡,医生开了西瓜霜喷雾。什么是西瓜霜治口腔溃疡原理? 病情分析:西瓜霜治口腔溃疡原理是杀菌,促进血液循环。西瓜
2024-01-16 08:24:01
原子弹爆炸的原理是各位朋友所需要解决的问题,问题理解之后可以给朋友带来很大的帮助,所以今天小编就给大家带来的详细讲解,一起来看看吧。原子弹爆炸的原理 原子弹爆炸的原理:利用核裂变释放的巨大能量杀人的武器。它基
2024-01-07 11:48:02
生活中,有许多的朋友最近问小编扬声器工作原理的问题,那么小编收集整合后,今天为大家分享关于的相关文章,一起来了解一下吧!扬声器工作原理 扬声器一般由三部分组成:磁环系统(永磁体、芯柱、导磁板)、振动系统(纸盆、音圈)
2024-01-06 23:18:01
抽水机原理超级多的小伙伴们都在问小编解决的方法,相信大家看完这篇,有什么区别?听听小编怎么说心中会有答案的,本期的内容都是满满的干货,千万不要错过哦!抽水机原理 依靠高速旋转的叶轮,液体在惯性离心力的作用下获得能量
2024-01-06 16:00:01
生活中有许多的朋友最近问小编电脑配置要怎么进行查看的问题,那么小编收集整合后,今天为大家分享关于的相关文章,一起来了解一下吧!电脑配置要怎么进行查看本文演示机型:联想肖鑫Air 14,适用系统:Windows 10;第一种方法是右
2024-01-06 08:42:01