大家好,关于cd ts是什么意思很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于开发自己的脚手架工具的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!
为什么要自己搭建项目?
这个事情起始于前两天给团队写一个脚手架工具,这段时间刚做做完一个系统,是团队第一个正式意义上的全栈项目;团队有自己的前端脚手架,但是没有后端脚手架,所以想着给团队写一个后端脚手架工具,这样团队在开展后续的全栈项目时可以使用脚手架构建项目,避免了重复搭建项目初始架构的大量工作,成员直接编写业务代码即可。
前两天用JavaScript完成了脚手架的初版,开发过程中发现没一点代码提示,很不舒服,而且这样的代码不利于后续的迭代和维护。
所以决定用typescript重构一遍,但是官方好像没有提供一个合适的脚手架工具,于是就开始自己搭建typescript项目;自己搭建最大的好处就是自主可控,项目中集成了实时编译的开发环境、eslint+prettier保证代码质量和风格统一、项目构建工具、git提交信息的规范化,这些都是一个项目最基本和必要的配置。
本来到这里就结束了,但是在后续重构脚手架的过程中发现一个问题,如果每写一个新的typescript项目就重复一遍这个搭建流程,比如:今天需要开发一个npm包,明天需要开发另外一个脚手架,这好像有点太麻烦了,于是就把整个搭建过程写成了一个脚手架,这样在后续开发的工作中就可以实现一键创建项目,简单、方便、舒爽
从这篇文章中你可以学到什么?
mkdirts-project&&cdts-project&&npminit-y&&npmitypescript-D&&npxtsc--init
这条命令的意思是在当前目录下创建一个ts-project目录,然后进入ts-project目录执行npminit-y初始话目录产生package.json文件,之后运行npmitypescript-D在开发环境安装typescript包,之后执行npxtsc--init生成tsconfig.json文件
之后所有的操作都以ts-project为根目录
mkdirsrc&&touchsrc/index.ts
新建src目录作为项目的源码目录(开发目录),并在src目录下创建index.ts文件作为项目的入口文件
如果一个目录下存在tsconfig.json文件,那就意味着这个目录是typescirpt项目的根目录,tsconfig.json文件中指定了用来编译项目的根文件和编译选项,使用tsc--init生成的tsconfig.json文件包含了大量的选项,其中大部分都被注释掉了,一般我们只需要配置如下内容即可:
{n"compileOnSave":true,n"compilerOptions":{n"target":"ES2018",n"module":"commonjs",n"moduleResolution":"node",n"experimentalDecorators":true,n"emitDecoratorMetadata":true,n"inlineSourceMap":true,n"noImplicitThis":true,n"noUnusedLocals":true,n"stripInternal":true,n"pretty":true,n"declaration":true,n"outDir":"lib",n"baseUrl":"./",n"paths":{n"*":["src/*"]n}n},n"exclude":[n"lib",n"node_modules"n]n}@types/node
npmi@types/node-D
这个是node.js的类型定义包
npmits-node-dev-D
在package.json的scripts中增加如下内容
{n"scripts":{n"dev:comment":"启动开发环境",n"dev":"ts-node-dev--respawn--transpile-onlysrc/index.ts"n}n}
执行npmrundev即可启动开发环境,并且修改文件时可实时编译
代码质量对于一个系统的可维护性、可迭代性至关重要,特别是在多人协作一个大型项目中,如果没有把控代码质量的工具,每人一套编码风格,这样的系统在后期的维护难度可想而知,基本上会成为一个难以迭代升级的祖传系统,除了重写别无他法。
因此控制代码质量的工具应运而生,而ESLint当属其中的佼佼者,熬死了各路的竞争者;typescript之前还在使用TSLint,但在2019年1月官方决定全面采用ESLint作为代码检查工具。
采用社区的开源配置方案eslint-config-standard,简单直接,足以hold住大部分项目了
npxeslint--init
以上流程走完以后在项目根目录会多出来一个.eslintrc.js文件,接下来在package.json的scripts中增加如下配置
{n"scripts":{n"eslint:comment":"使用ESLint检查并自动修复src目录下所有扩展名为.ts的文件",n"eslint":"eslint--fixsrc--ext.ts--max-warnings=0"n}n}Prettier
Perttier是一个专注于统一代码格式风格的工具,可能有人会疑惑,ESLint已经能够规范我们的代码,为什么还需要Prettier?简单来说是这样的,ESLint其实有两种类型规则:
其中格式规则主要是控制代码风格,简单理解就是代码看起来好看、易读,而质量规则主要是发现代码中存在的潜在bug或者可能会制造bug的地方,简单来说更多是从语法层面去考虑,比如现在禁止使用var声明变量,而prettier则是专注于格式规则,所以在格式方面我们选用更加专业的Prettier。
如果你同时使用ESLint和Prettier,且在编辑器中配置了SavaAutoFix时,会让你的一键格式化异常痛苦,因为在格式规则上有冲突,所以个人建议或者说不喜欢在编辑器中配置ESLint和Prettier,三个原因:
接下来就开始安装和配置Prettier
npmiprettier-D
安装Prettier所需的依赖,然后在项目目录增加.prettierrc.js,推荐配置如下:
module.exports={n//一行最多80字符nprintWidth:80,n//使用2个空格缩进ntabWidth:2,n//不使用tab缩进,而使用空格nuseTabs:false,n//行尾需要有分号nsemi:true,n//使用单引号代替双引号nsingleQuote:true,n//对象的key仅在必要时用引号nquoteProps:'as-needed',n//jsx不使用单引号,而使用双引号njsxSingleQuote:false,n//末尾使用逗号ntrailingComma:'all',n//大括号内的首尾需要空格{foo:bar}nbracketSpacing:true,n//jsx标签的反尖括号需要换行njsxBracketSameLine:false,n//箭头函数,只有一个参数的时候,也需要括号narrowParens:'always',n//每个文件格式化的范围是文件的全部内容nrangeStart:0,nrangeEnd:Infinity,n//不需要写文件开头的@prettiernrequirePragma:false,n//不需要自动在文件开头插入@prettierninsertPragma:false,n//使用默认的折行标准nproseWrap:'preserve',n//根据显示样式决定html要不要折行nhtmlWhitespaceSensitivity:'css',n//换行符使用lfnendOfLine:'lf'n}
在package.json的scripts中补充如下内容
{n"scripts":{n"prettier:comment":"自动格式化src目录下的所有.ts文件",n"prettier":"prettier--write\"src/**/*.ts\""n}n}
如果想在编辑器中配置ESLint和Prettier,具体怎么配查看这里,通过eslint-config-prettier来解决冲突问题,其作用就是关闭ESLint中的格式规则,只使用Prettier的格式规则
在系统开发中,如果git提交说明精准,在后期的协作以及bug处理时会变的有据可查,变相的提高了系统的可维护性,而且可以根据规范的提交说明快速生成开发日志,从而方便开发者或用户追踪项目的开发信息和功能特性。commitizen是一个实现规范提交说明的工具。
使用commitizen在项目中生成符合AngularJS规范的提交说明,并初始化cz-conventional-changelog适配器
npxcommitizeninitcz-conventional-changelog--save--save-exact
初始化时主要做了三件事:
{n"devDependencies":{n"cz-conventional-changelog":"^3.3.0"n},n"config":{n"commitizen":{n"path":"./node_modules/cz-conventional-changelog"n}n}n}
接下来安装校验工具,负责校验提交信息是否符合规范
npmi@commitlint/cli@commitlint/config-conventional-D
在项目根目录下新建commitlint.config.js并设置校验规则
module.exports={nextends:['@commitlint/config-conventional']n};
然后在package.json的scripts中增加如下内容
{n"scripts":{n"commit:comment":"引导设置规范化的提交信息",n"commit":"cz"n}n}
接下来,就只能使用规范化的提交信息了,如果不知道规范是什么,可在gitadd.之后执行npmruncommit代替gitcommit,会弹出一个列表,引导你一步步的填充符合规范的提交信息,熟练以后亦可用gitcommit
注意以下内容为第4版husky的使用方式。到目前为止,如果你的项目还没有执行过gitinit,即项目没有被git管理,则一定要先执行gitinit然后再往后进行,否则后面你需要重新安装一遍husky
npmihusky@4lint-staged-D
在package.json中添加如下内容
{n"husky":{n"hooks":{n"pre-commit":"lint-staged",n"commit-msg":"commitlint-EHUSKY_GIT_PARAMS"n}n},n"lint-staged":{n"*.ts":["npmruneslint","npmrunprettier"]n}n}
之前设置的ESLint、Prettier以及commitizen到目前为止都只限于开发者手动执行npmrunxx才能生效,这可不行,因为这一点都不智能,而且万一开发者忘执行命令了怎么办?
这时候就需要husky和lint-staged出场了,上述配置的原理其实就是监听了githook脚本的执行,在特定的命令执行前(pre-commit)执行相应的命令(lint-staged)。
注意这部分为husky@5的使用方式,和第4版不一样,如果还按照第4版的方式使用husky@5有问题,网上的解决方案也不可行
接下来使用gitcommit-m"message"就会看到hook生效了。
因为这个项目主要用于开发一些简单的typescript项目,比如项目组需要封装自己的npm包,所以就没有集成第三方的构建工具,直接用typescript自己的构建能力即可,简单易用,没有学习成本
{n"scripts":{n"build:comment":"构建",n"build":"npmruneslint&&npmrunprettier&&rm-rflib&&tsc--build",n}n}小结
好了,到这里项目就搭建好了,虽然还有一些可优化和扩展的地方,但是用于开发一个简单的npm包或者脚手架的项目来说已经足够了,如有需要可以基于以上内容再进行进一步的补充和扩展,希望大家能从里面得到自己需要的内容。
接下来就将上面的整个搭建过程封装成一个脚手架,脚手架的开发就在上面搭建的项目中进行
开发一个脚手架,一般都需要一些工具包的支持,项目中使用到了以下工具包:
上面列出的这些基本上就是目前开发一款脚手架常用的工具,接下来安装项目需要用到的工具包:
npmicommanderchalkshelljsinquirerclear-console-S本地调试
在项目根目录下的pacakge.json中增加如下内容:
{n"bin":{n"ts-cli":"./bin/ts-cli.js"n}n}
bin表示命令(ts-cli)的可执行文件的位置,接下来在项目根目录执行npmlink,将package.json中的属性bin的值路径添加全局链接,在命令行中执行ts-cli就会执行./bin/ts-cli.js文件
当用户安装带有bin字段的包时,如果是全局安装,npm将会使用符号链接把这些文件链接到/usr/local/node_modules/.bin/(即全局的node_modules/.bin中);如果是本地安装,会链接到./node_modules/.bin/。
开发结束可执行npmunlinkts-cli去掉ts-cli的链接,如果不幸你执行npmlink命令之后你改变了你的目录名,在unlink时会无效,只能手动去全局的node_modules中删除对应的软连接
在项目根目录下添加bin目录,然后在bin目录下新建ts-cli.js,文件内容如下:
#!/usr/bin/envnodenn//将构建目录(lib)下的index.js作为脚手架的入口nrequire('../lib/index')
接下来正式进入开发阶段
import{program}from'commander';nimportcreatefrom'./order/create';nn//ts-cli-v、ts-cli--versionn//临时禁用规则,保证这里可以通过require方法获取package.json中的版本号n/*eslint-disable@typescript-eslint/no-var-requires*/nprogramn.version(`${require('../package.json').version}`,'-v--version')n.usage('<command>[options]');nn//ts-clicreatenewPronprogramn.command('create<app-name>')n.description('Createnewprojectfrom=>ts-clicreateyourProjectName')n.action(async(name:string)=>{n//创建命令具体做的事情都在这里,name是你指定的newPronawaitcreate(name);n});nnprogram.parse(process.argv);n/src/order/create.ts
/**n*create命令的具体任务n*/nnimport{nchangePackageInfo,nend,ninitProjectDir,ninstallDevEnviroment,ninstallFeature,ninstallTSAndInit,ninstallTypesNode,nisFileExist,nselectFeature,n}from'../utils/create';nn//create命令nexportdefaultasyncfunctioncreate(projecrName:string):Promise<void>{n//判断文件是否已经存在nisFileExist(projecrName);n//选择需要的功能nconstfeature=awaitselectFeature();n//初始化项目目录ninitProjectDir(projecrName);n//改写项目的package.json基本信息,比如name、descriptionnchangePackageInfo(projecrName);n//安装typescript并初始化ninstallTSAndInit();n//安装@types/nodeninstallTypesNode();n//安装开发环境,支持实时编译ninstallDevEnviroment();n//安装featureninstallFeature(feature);n//结束nend(projecrName);n}n/src/utils/create.ts
/**n*create命令需要用到的所有方法n*/nimport{ngetProjectPath,nPackageJSON,nJSON,nprintMsg,nreadJsonFile,nwriteJsonFile,nclearConsole,n}from'../utils/common';nimport{existsSync}from'fs';nimport{prompt}from'inquirer';nimport{blue,cyan,gray,red,yellow}from'chalk';nimport*asshellfrom'shelljs';nimport*asinstallFeatureMethodfrom'./installFeature';nn/**n*验证当前目录下是否已经存在指定文件,如果存在则退出进行n*@paramfilename文件名n*/nexportfunctionisFileExist(filename:string):void{n//文件路径nconstfile=getProjectPath(filename);n//验证文件是否已经存在,存在则推出进程nif(existsSync(file)){nprintMsg(red(`${file}已经存在`));nprocess.exit(1);n}n}nn/**n*交互式命令行,让用户自己选择需要的功能n*return['ESLint','Prettier','CZ']n*/nexportasyncfunctionselectFeature():Promise<Array<string>>{n//清空命令行nclearConsole();n//输出信息n/*eslint-disable@typescript-eslint/no-var-requires*/nprintMsg(blue(`TSCLIv${require('../../package.json').version}`));nprintMsg('Startinitializingtheproject:');nprintMsg('');n//选择功能,这里配合下面的installFeature方法和./installFeature.ts文件为脚手架提供了良好的扩展机制n//将来扩展其它功能只需要在choices数组中增加配置项,然后在./installFeature.ts文件中增加相应的安装方法即可nconst{feature}=awaitprompt([n{nname:'feature',ntype:'checkbox',nmessage:'Checkthefeaturesneededforyourproject',nchoices:[n{name:'ESLint',value:'ESLint'},n{name:'Prettier',value:'Prettier'},n{name:'CZ',value:'CZ'},n],n},n]);nnreturnfeatureasArray<string>;n}nn/**n*初始化项目目录n*/nexportfunctioninitProjectDir(projectName:string):void{nshell.exec(`mkdir${projectName}`);nshell.cd(projectName);nshell.exec('npminit-y');n}nn/**n*改写项目中package.json的name、descriptionn*/nexportfunctionchangePackageInfo(projectName:string):void{nconstpackageJSON:PackageJSON=readJsonFile<PackageJSON>('./package.json');npackageJSON.name=packageJSON.description=projectName;nwriteJsonFile<PackageJSON>('./package.json',packageJSON);n}nn/**n*安装typescript并初始化n*/nexportfunctioninstallTSAndInit():void{n//安装typescript并执行命令tsc--init生成tsconfig.jsonnshell.exec('npmitypescript-D&&npxtsc--init');n//覆写tsconfig.jsonnconsttsconfigJson:JSON={ncompileOnSave:true,ncompilerOptions:{ntarget:'ES2018',nmodule:'commonjs',nmoduleResolution:'node',nexperimentalDecorators:true,nemitDecoratorMetadata:true,ninlineSourceMap:true,nnoImplicitThis:true,nnoUnusedLocals:true,nstripInternal:true,npretty:true,ndeclaration:true,noutDir:'lib',nbaseUrl:'./',npaths:{n'*':['src/*'],n},n},nexclude:['lib','node_modules'],n};nwriteJsonFile<JSON>('./tsconfig.json',tsconfigJson);n//创建src目录和/src/index.tsnshell.exec('mkdirsrc&&touchsrc/index.ts');n}nn/**n*安装@types/noden*这是node.js的类型定义包n*/nexportfunctioninstallTypesNode():void{nshell.exec('npmi@types/node-D');n}nn/**n*安装开发环境,支持实时编译n*/nexportfunctioninstallDevEnviroment():void{nshell.exec('npmits-node-dev-D');n/**n*在package.json的scripts中增加如下内容n*"dev:comment":"启动开发环境",n*"dev":"ts-node-dev--respawn--transpile-onlysrc/index.ts"n*/nconstpackageJson=readJsonFile<PackageJSON>('./package.json');npackageJson.scripts['dev:comment']='启动开发环境';npackageJson.scripts['dev']=n'ts-node-dev--respawn--transpile-onlysrc/index.ts';nwriteJsonFile<PackageJSON>('./package.json',packageJson);n}nn/**n*安装用户选择的功能n*@paramfeature功能列表n*/nexportfunctioninstallFeature(feature:Array<string>):void{nfeature.forEach((item)=>{nconstfunc=(installFeatureMethod[n`install${item}`n]asunknown)as()=>void;nfunc();n});n//安装husky和lint-stagedninstallHusky(feature);n//安装构建工具ninstallFeatureMethod.installBuild(feature);n}nn/**n*安装husky和lint-staged,并根据功能设置相关命令n*@paramfeature用户选择的功能列表n*/nfunctioninstallHusky(feature:Array<string>):void{n//feature副本nconstfeatureBak=JSON.parse(JSON.stringify(feature));nn//设置hooknconsthooks={};n//判断用户是否选择了CZ,有则设置hooksnif(featureBak.includes('CZ')){nhooks['commit-msg']='commitlint-EHUSKY_GIT_PARAMS';n}nn//设置lintStagednconstlintStaged:Array<string>=[];nif(featureBak.includes('ESLint')){nlintStaged.push('eslint');n}nif(featureBak.includes('Prettier')){nlintStaged.push('prettier');n}nninstallFeatureMethod.installHusky(hooks,lintStaged);n}nn/**n*整个项目安装结束,给用户提示信息n*/nexportfunctionend(projectName:string):void{nprintMsg(`Successfullycreatedproject${yellow(projectName)}`);nprintMsg('Getstartedwiththefollowingcommands:');nprintMsg('');nprintMsg(`${gray('$')}${cyan('cd'+projectName)}`);nprintMsg(`${gray('$')}${cyan('npmrundev')}`);nprintMsg('');n}/src/utils/installFeature.ts
/**n*实现各个功能的安装方法n*/nimport*asshellfrom'shelljs';nimport{writeFileSync}from'fs';nimport{PackageJSON,printMsg,readJsonFile,writeJsonFile}from'./common';nimport{red}from'chalk';nn/**n*安装ESLintn*/nexportfunctioninstallESLint():void{nshell.exec(n'npmieslint@typescript-eslint/parser@typescript-eslint/eslint-plugin-D',n);n//添加.eslintrc.jsnconsteslintrc=`module.exports={n"env":{n"es2021":true,n"node":truen},n"extends":[n"eslint:recommended",n"plugin:@typescript-eslint/recommended"n],n"parser":"@typescript-eslint/parser",n"parserOptions":{n"ecmaVersion":12,n"sourceType":"module"n},n"plugins":[n"@typescript-eslint"n],n"rules":{n}n};n`;ntry{nwriteFileSync('./.eslintrc.js',eslintrc,{encoding:'utf-8'});n}catch(err){nprintMsg(`${red('Failedtowrite.eslintrc.jsfilecontent')}`);nprintMsg(`${red('Pleaseaddthefollowingcontentin.eslintrc.js')}`);nprintMsg(`${red(eslintrc)}`);n}nn//改写package.jsonnconstpackageJson=readJsonFile<PackageJSON>('./package.json');npackageJson.scripts['eslint:comment']=n'使用ESLint检查并自动修复src目录下所有扩展名为.ts的文件';npackageJson.scripts['eslint']='eslint--fixsrc--ext.ts--max-warnings=0';nwriteJsonFile<PackageJSON>('./package.json',packageJson);n}nn/**n*安装Prettiern*/nexportfunctioninstallPrettier():void{nshell.exec('npmiprettier-D');n//添加.prettierrc.jsnconstprettierrc=`module.exports={n//一行最多80字符nprintWidth:80,n//使用2个空格缩进ntabWidth:2,n//不使用tab缩进,而使用空格nuseTabs:false,n//行尾需要有分号nsemi:true,n//使用单引号代替双引号nsingleQuote:true,n//对象的key仅在必要时用引号nquoteProps:'as-needed',n//jsx不使用单引号,而使用双引号njsxSingleQuote:false,n//末尾使用逗号ntrailingComma:'all',n//大括号内的首尾需要空格{foo:bar}nbracketSpacing:true,n//jsx标签的反尖括号需要换行njsxBracketSameLine:false,n//箭头函数,只有一个参数的时候,也需要括号narrowParens:'always',n//每个文件格式化的范围是文件的全部内容nrangeStart:0,nrangeEnd:Infinity,n//不需要写文件开头的@prettiernrequirePragma:false,n//不需要自动在文件开头插入@prettierninsertPragma:false,n//使用默认的折行标准nproseWrap:'preserve',n//根据显示样式决定html要不要折行nhtmlWhitespaceSensitivity:'css',n//换行符使用lfnendOfLine:'lf'n};n`;ntry{nwriteFileSync('./.prettierrc.js',prettierrc,{encoding:'utf-8'});n}catch(err){nprintMsg(`${red('Failedtowrite.prettierrc.jsfilecontent')}`);nprintMsg(`${red('Pleaseaddthefollowingcontentin.prettierrc.js')}`);nprintMsg(`${red(prettierrc)}`);n}n//改写package.jsonnconstpackageJson=readJsonFile<PackageJSON>('./package.json');npackageJson.scripts['prettier:comment']=n'自动格式化src目录下的所有.ts文件';npackageJson.scripts['prettier']='prettier--write"src/**/*.ts"';nwriteJsonFile<PackageJSON>('./package.json',packageJson);n}nn/**n*安装CZ,规范git提交信息n*/nexportfunctioninstallCZ():void{nshell.exec(n'npxcommitizeninitcz-conventional-changelog--save--save-exact',n);nshell.exec('npmi@commitlint/cli@commitlint/config-conventional-D');n//添加commitlint.config.jsnconstcommitlint=`module.exports={nextends:['@commitlint/config-conventional']n};n`;ntry{nwriteFileSync('./commitlint.config.js',commitlint,{encoding:'utf-8'});n}catch(err){nprintMsg(`${red('Failedtowritecommitlint.config.jsfilecontent')}`);nprintMsg(n`${red('Pleaseaddthefollowingcontentincommitlint.config.js')}`,n);nprintMsg(`${red(commitlint)}`);n}n//改写package.jsonnconstpackageJson=readJsonFile<PackageJSON>('./package.json');npackageJson.scripts['commit:comment']='引导设置规范化的提交信息';npackageJson.scripts['commit']='cz';nwriteJsonFile<PackageJSON>('./package.json',packageJson);n}nn/**n*安装husky和lint-staged,以实现gitcommit时自动化校验n*@paramhooks,需要自动执行的钩子n*@paramlintStaged,需要钩子运行的命令n*/nexportfunctioninstallHusky(nhooks:{[key:string]:string},nlintStaged:Array<string>,n):void{n//初始化git仓库nshell.exec('gitinit');n//在安装husky和lint-stagednshell.exec('npmihuskylint-staged-D');n//设置package.jsonnconstpackageJson=readJsonFile<PackageJSON>('./package.json');npackageJson['husky']={nhooks:{n'pre-commit':'lint-staged',n...hooks,n},n};npackageJson['lint-staged']={n'*.ts':lintStaged.map((item)=>`npmrun${item}`),n};nwriteJsonFile<PackageJSON>('./package.json',packageJson);n}nn/**n*安装构建工具,目前主要用于小项目,所以使用typescript原生的构建功能即可n*/nexportfunctioninstallBuild(feature:Array<string>):void{n//设置package.jsonnconstpackageJson=readJsonFile<PackageJSON>('./package.json');npackageJson.scripts['build:comment']='构建';nletorder='';nif(feature.includes('ESLint')){norder+='npmruneslint';n}nif(feature.includes('Prettier')){norder+='&&npmrunprettier';n}norder+='&&rm-rflib&&tsc--build';npackageJson.scripts['build']=order;nwriteJsonFile<PackageJSON>('./package.json',packageJson);n}n/src/utils/common.ts
/**n*放一些通用的工具方法n*/nimport{readFileSync,writeFileSync}from'fs';nimport{resolve}from'path';nimport*asclearfrom'clear-console';nnexportinterfacePackageJSON{nname:string;nversion:string;ndescription:string;nscripts:{n[key:string]:string;n};n}nnexportinterfaceJSON{n[key:string]:unknown;n}nn/**n*读取指定路径下json文件n*@paramfilenamejson文件的路径n*/nexportfunctionreadJsonFile<T>(filename:string):T{nreturnJSON.parse(readFileSync(filename,{encoding:'utf-8',flag:'r'}));n}nn/**n*覆写指定路径下的json文件n*@paramfilenamejson文件的路径n*@paramcontentjson内容n*/nexportfunctionwriteJsonFile<T>(filename:string,content:T):void{nwriteFileSync(filename,JSON.stringify(content,null,2));n}nn/**n*获取项目绝对路径n*@paramprojectName项目名n*/nexportfunctiongetProjectPath(projectName:string):string{nreturnresolve(process.cwd(),projectName);n}nn/**n*打印信息n*@parammsg信息n*/nexportfunctionprintMsg(msg:string):void{nconsole.log(msg);n}nn/**n*清空命令行n*/nexportfunctionclearConsole():void{nclear();n}n构建
执行npmrunbuild进行构建,构建时会进行代码质量和风格的检查,有些问题可以自动修复,有些不行,不行的按照提示手动修复一下即可,然后重新构建
构建完成以后找个测试目录,执行ts-cli-v或者ts-cli--version查看脚手架的版本
执行ts-clicreatetest可创建一个名为test的typescript项目
{n"name":"@liyongning/ts-cli"n"main":"./lib/index.js",n"keywords":["typescript","cli","typescript脚手架","ts脚手架","ts-cli","脚手架"],n"author":"李永宁",n"files":["package.json","README.md","lib"],n"repository":{n"type":"git",n"url":"https://github.com/liyongning/ts-cli.git"n},n}name:包名,在包名称前加自己的npm账户名,采用npmscope的方式,包目录的组织方式和普通包不一样,而且可以有效的避免和他人的包名冲突main:表示包的入口位置keywords:关键字,方面别人搜索到你的包files:告诉npm,publish时发布哪些包到npm仓库repository:项目仓库
npm的账户名、密码就不用说,必不可少
在项目根目录下增加一个发布脚本publish.sh
#!/bin/bashnnecho'开始构建脚手架'nnnpmrunbuildnnecho'脚手架构建完成,现在发布'nnnpmpublish--accesspublic
接下来开始发布,在项目根目录下一次运行如下命令:
npmlogin
根据提示依次输入相关信息,然后执行下面的命令完成发布
shpublish.sh
登陆npm查看
好了,到这里项目就搭建和脚手架的封装就彻底结束了,虽然还有一些可优化和扩展的地方,但是对于开发一个简单的库或者脚手架的项目来说这个脚手架已经完全够用了
如有需要也可以自行去扩展,因为脚手架内置了不错的扩展性,不论是为已有的create命令增加新的功能,还是新增一个命令,都很简单,方便你根据自身需要进行二次开发
如果你还想了解更多这方面的信息,记得收藏关注本站。
还没有评论,来说两句吧...