开发工具:
文件大小: 793kb
下载次数: 0
上传时间: 2019-09-02
详细说明:手写cli脚手架文档,写自己的脚手架,30分钟入门教程~const program require( commander )i
program version(0.0.1)
parse( process.argv);// process.argv就是用户在命令行中传入的参数
执行zhu-c1i-help是不是已经有一提示了!(珠峰架构)
这个版本号应该使用的是当前c项目的版本号,我们需要动态获取,并且为了方便我们将常量全部放到
ut下的 constants文件夹中(珠峰架构)
const i name, version= require(././package json);
module exports =t
name
version
这样我们就可以动态获取版本号了
const program require( commander '
const i version= require(./utils/constants
program version(version)
parse(process. argv);
32配置指令命令
根据我们想要实现的功能配置执行动作,遍历产生对应的命令
const actionsMap =t
create:[//创建樸板
description: ' create project
alias: cr
examples: D
zhu-cli create
config:{//配置配置文件
description: config info'
alas: C
examples:
zhu-cli config get
zhu-cli config set
description: command not found
/循环创建命令
object keys (actionsMap) forEach((action)=>t
program
command( action)//命令的名称
a1ias( actionsMap[ action]. alias)//命令的别名
description( actionsMap[ action]. description)//命令的描述
action((=>{//动作
console. log (action)
})
program version(version)
parse(process. argv)
33编写hep命令
监听help命令打印帮助信息(珠峰架构)
program on('--help,(=>[
console. log(Examples);
object keys (actionsMap) forEach((action)=>i
CactionsMap [action]. examples |I []) forEach((example)
console. log( Example
);
到现在我们已经把命令行配置的很棒啦,接下来就开始实现对应的功能!
4 create命令
create命令的主要作用就是去g仓库中拉取模板并下载对应的版本到本地,如果有模板则根据用户填写
的信息渲染好模板,生成到当前运行命令的目录下~
action((={//动作
if( action===*"){//如果动作没匹配到说明输入有误
console. log Caci tonMap [action] description)
}else{//引用对应的动作文件将参数传入
require (path. resolve dirname, action))(. process. argv. slice(3))
根据不同的动作,动态引入对应模块的文件(珠峰架构
创建 create s
//创建项目
module exports async (projectName)=>[
console. log (projectName)
执行 Zhu-cli create project,可以打印出 project
41拉取项目
我们需要获取仓库中的所有模板信息,我的模板全部放在了git上,这里就以gt为例,我通过 axIos去获
取相关的信息
(珠峰架构)
axles
这里借助下 github的pi
const axios require( axios);
//1).获取仓库列表
const fetchRepoList async (=> i
/获取当前组织中的所有仓库信息,这个仓库中存放的都是项目模板
constidata3=awaitaxios.get(https://api.github.com/orgs/zhu-cli/repos);
return data
module exports async (projectName)=> I
let repos await fetchRepolistO
repos repos map((item)=> item name);
console. log repos)
发现在安装的时候体验很不好没有任何提示,而且最终的结果我希望是可以供用户选择的!
4.2 inquirer ora
我们来解决上面提到的问题(珠峰架构)
npm 1 InquIrer ora
module exports async (projectName)=>[
const spinner ora( fetching repo list')
spinner. start();//开始 loading
let repos await fetchrepolisto)
spInner. succeed(;//结束 loading
/选择模板
repos repos map((item)=> item name)
const i repo= await Inquirer. prompt(i
name: repo
type: ' list'
message: please choice repo temp late to create project
choices: repos,//选择模式
console. log (repo)
我们看到的命令行中选择的功能基本都是基于 iNquirer实现的,可以实现不同的询问方式
43获取版本信息
和获取模板一样,我们可以故技重施(珠峰架构)
const fetchTaglist async (repo)=> i
constidata3=awaitaxios.get(https://api.github.com/repos/zhu
cli/s[repo]/tags
return data
//获取版本信息
spinner ora( fetching repo tags )
spinner. start
let tags await fetchTagList (repo)
spInner. succeed();//结束 loading
/选择版本
tags tags, map ((item)=> item name);
consti tag]= await Inquirer. prompt(i
name: tag
type: ' list
message: ' please choice repo template to create project
choices: tags
我们发现每次都需要去开启 Loading、关闭 oading,重复的代码当然不能放过啦!我们来简单的封装下
const wrapFetchAddloding =(fn, message)=> async (.. args)=> i
const spinner ora(message);
spInner. start();//开始 loading
const r= await fn(.args)
spinner. succeed;//结束 loading
return r
}
/这回用起来舒心多了
let repos await wrapFetchAddloding(fetchRepolist, 'fetching repo list )O
let tags await wrapFetchAddlodingcfetchTagList, fetching tag list )(repo)
44下载项目
我们已经成功获取到了项目模板名称和对应的版本,那我们就可以直接下载啦!(珠峰架构)
npm i download-git-repo
很遗憾的是这个方法不是 promise方法,没关系我们自己包装一下
const i promisify]- require(util);
const downLoadGit= require( down load-git-repo)
downLoadGit= promisify(downLoadGit)
node中已经帮你提供了一个现成的方法,将异步的ap可以快速转化成 promise的形式~
下载前先找个临时目录来存放下载的文件来~继续配置常量(珠峰架构)
const down loadDirectory =Siprocess env [process platform ===darwin?HOME
:'USERPROFILE'J3/ template
这里我们将文件下载到当前用户下的. template文件中由于系统的不同目录获取方式不一
样, process. platform在 windows下获取的是win32我这里是mac所有获取的值是 darwin,在根据
对应的环境变量获取到用户目录
const down load async (repo, tag)=> i
et ap
zhu-c11/${repo};//下载项目
if ctag)i
api +=#stagh
const dest=^${ down loadDirectory}/${repo};//将模板下载到对应的目录中
await downLoadGit (api, dest);
return dest;//返回下载目录
//下载项
const target await wrapFetchAddLoding (down load, down load template ')(re
tag)
如果对于简单的项目可以直接把下载好的项目拷贝到当前执行命令的目录下即可
安装np可以实现文件的拷贝功能(珠峰架构)
npm
像这样:
let ncp= require(ncp);
ncp= promis fy(ncp);
/将下载的文件拷贝到当前执行命令的目录下
await ncp(target, path. join (path. resolve, projectName));
当然这里可以做的更严谨一些,判断一下当前目录下是否有重名文件等…,还有很多细节也需要考虑像多
次创建项目是否要利用已经下载好的模板,大家可以自由的发挥
4.5模板编译
刚才说的是简单文件,那当然直接拷贝就好了,但是有的时候用户可以定制下载模板中的内容,拿
package.jso文件为例,用户可以根据提示给项目命名、设置描述等(珠峰架枃)
这里我在项目模板中增加了askj
module exports=[
type: confi
name: private
message: ths resgistery is private?
},
根据对应的询问生成最终的 package.json
下载的模板中使用了ejs模板(珠峰架构)
name
de-temp late
version
0.1.2",
" private":"<‰= private‰"
scripts":t
erve
vue-cli-service serve
build vue-cli-service build
dependencies": i
yue
A2.6.10"
autor.
<%=author%
description":<%=description%>
devDependencies":i
vue/cli-service":A3 11.0
"vue-template-compiler:"A2 6.10
1 I cense":"<‰=1 cense‰"
写到这里,大家应该想到了!核心原理就是将下载的模板文件,依次遍历根据用户填写的信息渲
染模板,将渲染好的结果拷贝到执行命令的目录下
安装需要用到的模块(珠峰架枃)
npm i metal smith ejs consolidate
const metalsmith= require(' metalsmith");//历文件火
let i render]- require( consolidate).ejs;
ender= promisify( render);//包装渲染方法
//没有ask文件说明不需要编译
if (!fs. existssync(path. join (target, 'ask. js )))t
await ncp(target, path. join (path. resolve, projectName));
await new Promi se((resovle, reject)=> t
Metalsmith( dirname)
source( target)//遍历下载的目录
destination(path.join(path. resolve(), projectname))//输出渲染后的结果
use Async (files, metal, done)=>i
//弹框询问用
const result= await Inquirer. prompt (require(path. join(target
ask. js)));
const data = metal metadata
object. assign(data, result);//将询问的结果放到 metadata中保证在下一个中间件中
可以获取到
delete files[ ask. js]
done o
use((files, metal, done)=>t
reflect. ownkeys(files). forEach (async (file)=>t
let content= files[file]. contents. tostring(;//获取文件中的内容
if(file. includes(.js")file. includes(,json')){//如果是js或者
json才有可能是模板
if〔 content. includes('<%'))[//文件中用<%我才需要编译
content= await render( content, metal. metadata());//用数据渲染模板
files[file]. contents= Buffer.from( content);//渲染好的结果替换即可
one
build((err)=>{//执行中间件
if (err)t
resovled
3 else i
reject O
});
文里的逻辑就是上面描述的那样,实现了模板替换!到此安装项目的功能就完成了,我们发现这
里面所有用到的地址的路径都写死了,我们希望这是一个更通用的脚手架,可以让用户自己配置
拉取的地址
5 config命令
新建con!js主要的作用其实就是配置文件的读写操作,当然如果配置文件不存在需要提供默认的值,
先来编写常量(珠峰架构)
constants.js的配置
const configFile Sprocess. env [process platform ==='darwin?HOME:
USERPROFILE']}/. zhuo;//配置文件的存储位置
const defaul tconfig =t
repo:'zhu-cli’,//默认拉取的仓库名
编写 config.js
const fs= require( fs);
const t defau ltconfig, configFile require(./util/constants ')
module exports= Action, k, v)=>i
if (action ==='get)i
console.log(获取');
3 else if action ==='set)i
console.log("设置");
一般rc类型的配置文件都是ini格式也就是
repo=zhu-c1i
register=gi thub
下载in讠模块解析配置文件(珠峰架构)
npm 1 1nT
这里的代码很简单,无非就是文件操作了
const fs require( fs)
const i encode, decode ]= requirec ini);
const i defau l tconfig, configFile]= require(. /util/constants)
const fs require( fs );
const i encode, decode]= require( ini)
const i defau l tConfig, configFile )=require(./util/constants)
module exports= (action, k,v
const flag= fs. existsSync (configFile);
const obj=0;
if(f1ag){//配置文件存在
const content= fs. readFilesync(configFile,utf8)
const c= decode( content);//将文件解析成对象
object. assign (obj, c)
if action ===get )i
console. log (obj[k] defaul tConfig[k])
3 else if action ===set)i
obj[k]=v
fs. writeFilesync( configfile, encode(obj));//将内容转化in格式写入到字符串中
console. log( Sik]=siv
3 else if action ==='getval)f
return bilk]
geta1这个方法是为了在执行 create命令时可以获取到配置变量(珠峰架构)
const config require(./config);
const repoUrl= config('getval','repo):
这样我们可以将 create方法中所有的zhu-c1i全部用获取到的值替换掉啦!
到此基本核心的方法已经ok!剩下的大家可以自行扩展啦!
6项目发布
终于走到最后一步啦我们将项目推送npm上流程不再赘述啦!
nrm use npm
npm pub1ish#已经发布成功
可以通过 npm install zhu-cli -g进行安装啦!(珠峰架构)
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.