当前位置: 首页 > 后端技术 > Node.js

搭建一个创建组件库的项目脚手架工具(如Vue-cli3)

时间:2023-04-03 12:15:25 Node.js

鍏徃鏈€杩戞兂鎼缓涓€涓鏈夌殑npm浠撳簱锛屾槸涓轰簡鎶婂钩鏃剁敤寰楁瘮杈冮绻佺殑宸ュ叿鎴栬€呯粍浠跺垎寮€锛岃繖鏍峰氨鍙互鍒嗙绠$悊锛岄殢鐫€椤圭洰瑙勬ā瓒婃潵瓒婂ぇ锛屾暟閲忚秺鏉ヨ秺澶氾紝绠€鍗曠殑澶嶅埗绮樿创鏃犵枒宸茬粡涓嶈兘婊¤冻鎴戜滑鍦ㄤ紭闆呭拰瀹炵敤鏂归潰鐨勯渶姹傦紝杩涗竴姝ョ殑妯″潡鍖栨槸蹇呯劧鐨勩€備絾鏄粍浠跺簱鐨勫缓绔嬪叾瀹炴槸涓€涓緢楹荤儲鐨勮繃绋嬨€傚熀鏈殑webpack鐨勯厤缃氨涓嶇敤澶氳浜嗭紝鎺ヤ笅鏉ヨ繕闇€瑕佸姞涓€浜沞s-lint绛夊伐鍏锋潵瑙勮寖鍥㈤槦鎴愬憳鐨勪唬鐮併€傚湪寮€鍙戣繃绋嬩腑锛屼负浜嗘柟渚垮紑鍙戠粍浠讹紝鑷劧闇€瑕佷竴涓洰褰曟潵瀛樻斁浣跨敤绀轰緥锛岀劧鍚庤繕瑕佸垱寤轰竴涓墦鍖呰鑼冿紝鍙戝竷鍒颁竴涓鏈夌殑npm浠撳簱涓€傝繖鏍蜂竴鏉ワ紝鎴戜滑鐨勭Н鏋佹€у娍蹇呬細澶ф墦鎶樻墸锛屾墍浠ヤ笉濡傚仛涓€涓惌寤烘ā鍧楀寘鐨勮剼鎵嬫灦宸ュ叿锛屾柟渚挎垜浠」鐩殑鍒濆鍖栥€俆ips锛氭渶缁堜骇鍝佹槸搴曢儴鐨勭鏈塏PM銆傝繖閲岀畝鍗曟彁涓€涓嬬鏈塶pm鐨勬惌寤恒€俷pmiverdaccio-gpm2startverdaccio鎺ㄨ崘閰嶅悎nrm浣跨敤锛屽揩閫熷垏鎹粨搴撳湴鍧€verdacciogithub涔熸湁瀹屾暣鐨勬剰澶у埄鍚嶅瓧锛岀湡娲嬫皵銆傚伐鍏峰湪杩涘叆涓婚涔嬪墠锛岃鎴戜粙缁嶄竴浜涘叧閿偣鍜屽伐鍏枫€傛湁浜嗚繖浜涘啓浣滅殑瑕佺偣锛屽叾瀹炲啓璧锋潵杩樻槸鎸虹畝鍗曠殑銆俷pmbin鏈夋病鏈夋兂杩囦竴浜涘叏灞€瀹夎鐨勫伐鍏凤紝浠栨€庝箞鑳藉湪鍛戒护琛屼腑闅忔剰璋冪敤鍛紵鍏跺疄杩欎釜涓滆タ灏辨槸npm鎻愪緵鐨勯摼鎺ュ姛鑳?/package.json{"name":"lucky-for-you","bin":{"lucky":"bin/lucky"}}褰撹繖鏍蜂竴涓ā鍧楀凡鍙戝竷锛屼竴鏃︽湁浜轰娇鐢?g鍙傛暟鍏ㄥ眬瀹夎sudonpmiluck-for-you-g/usr/local/bin/lucky->/usr/local/lib/node_modules/luckytiger-package-cli/bin/lucky#npm浼氬府浣犻摼鎺pm瀹為檯涓婁細甯綘閾炬帴涓€娆★紝閾炬帴鍒颁綘鎿嶄綔绯荤粺鐨凱ath杩欐牱锛屽綋浣犺緭鍏ュ懡浠ucky鏃讹紝浣犲氨鍙互鎴愬姛鍦颁粠璺緞涓壘鍒板搴旂殑绋嬪簭銆傝繕鏈変竴鐐瑰氨鏄紝鐢ㄤ簬閾炬帴鎵ц鐨勬枃浠讹紝涓€鑸兘浼氬湪寮€澶村姞涓婂涓嬪唴瀹癸紝杩欐牱bash鎵嶈兘姝g‘璇嗗埆鏂囦欢搴旇濡備綍鎵ц#!/usr/bin/envnode//琛ㄧず浣跨敤node鏉ヨ繍琛屾枃浠?/鎺ヤ笅鏉criptCommander.jstj澶х鐨勪綔鍝侊紝鏂逛究鍐欏懡浠よ宸ュ叿銆傚彲浠ヨ嚜鍔ㄧ敓鎴愬府鍔╁懡浠onstprogram=require('commander');program.version('0.0.1').usage('[options]');program.command('create').description('鍒涘缓涓€涓叏鏂扮殑npm缁勪欢妯″潡').action((name,cmd)=>{constoptions=cleanArgs(cmd);require('../lib/create')(name,options);});//鐢ㄦ埛娌℃湁杈撳叆瀹屾暣鐨勫懡浠よ緭鍑哄府鍔﹊f(!process.argv.slice(2).length){program.outputHelp();}program.parse(process.argv);Commander.jsgithubinquirer鍏跺疄褰撴垜绗竴娆′娇鐢╲ue-cli3.0鐨勬椂鍊欙紝閲岄潰鐨勫懡浠よ褰㈠紡鐪熺殑寰堟儕鑹炽€傜炕浜唙ue-cli3鐨勬簮鐮佹壘鍒颁簡杩欎釜宸ュ叿锛岀敤浜庡懡浠よ褰㈠紡銆傚惎鐢ㄦ洿鐩磋鐨勯厤缃€夐」銆俰nquirer.prompt([{type:'list',name:'template',message:'template:Pleaseselectaprojectstartertemplate',choices:[{key:'1',name:'JavaScriptLibrary-fornormalJSlibrary',value:'js-lib',},{key:'2',name:'Vue-components-forVuecomponentlibrary',value:'vue-component',},],},{type:'input',name:'author',message:'author:Pleaseenteryourname',validate:function(value){return!!value;},},{type:'input',name:'desc',message:'desc:Pleaseenteraprojectdescription',validate:function(value){return!!value;},},{type:'confirm',name:'confirm',message:'confirm:閰嶇疆瀹屾垚浜嗗悧锛?,榛樿:false,},]).then(answers=>{console.log(answers.template);console.log(answers.author);console.log(answers.desc);});杩樻湁琛ㄥ崟鐨勭绫诲緢澶氾紝鏈€绠€鍗曠殑list+input+confirm瀵规垜鏉ヨ灏卞浜嗐€傛煡璇ithub寮€濮嬫惌寤虹幇鍦ㄥ垎浜竴涓嬫垜鐨勬惌寤鸿繃绋嬨€傜敱浜庝唬鐮侀噺杈冨ぇ锛屾病蹇呰涓€涓€璐村嚭鏂囦欢锛岃繖閲屽彧鍋氱畝鍗曚粙缁嶏紝鍏蜂綋鍙互鏌ョ湅鎴戠殑github椤圭洰銆傛垜澶ц嚧灏嗘垜鐨刢li宸ュ叿鍒嗕负涓ら儴鍒嗭細template妯℃澘+creatorzcreator鐨勪富瑕佸姛鑳芥槸鍚告敹鐢ㄦ埛鐨勯€夋嫨锛屼互鍙婂熀浜庢ā鏉跨殑copy+render銆倂ue-cli3.0杩欓儴鍒嗘搷浣滀細姣旇緝澶嶆潅銆傚畠灏嗘ā鏉夸腑鐨勫叿浣撳姛鑳芥娊璞℃垚涓€涓狿lugin锛屽彲浠ユ寜闇€鏋勫缓妯℃澘锛屽綋鐒舵洿閫傚悎澶т紬浣跨敤銆備絾鏄洜涓烘垜鐨勯」鐩槸缁欏叕鍙稿唴閮ㄤ娇鐢ㄧ殑锛屼笉闇€瑕佸お绗肩粺鐨勮璁°€備竴涓ā鏉垮彲浠ョ洿鎺ヨВ鍐充竴涓棶棰橈紝绠€鍖栨ā鍨嬨€傛瘮濡傜敤妯℃澘鍒涘缓Vue缁勪欢搴擄紝鐢ㄦā鏉垮垱寤篟eact缁勪欢搴擄紝鐢ㄦā鏉垮垱寤篔avaScript宸ュ叿鍑芥暟搴撱€傝繖鏍锋垜浠殑妯℃澘templatecreator鍙互鍦ㄤ竴瀹氱▼搴︿笂瑙h€︼紝涔熷氨鏄浠ュ悗闇€瑕佹洿澶氱绫荤殑妯℃澘锛屼笉闇€瑕佸幓淇敼creator閮ㄥ垎鐨勪唬鐮併€傜洰褰曠粨鏋勨敎鈹€鈹€README.md鈹溾攢鈹€bin鈹傗敂鈹€鈹€lucky#mainprogram鈹溾攢鈹€lib鈹傗敎鈹€鈹€copy.js#copy鈹傗敂鈹€鈹€create.js#maincreator鈹溾攢鈹€package-lock.json鈹溾攢鈹€package.json鈹溾攢鈹€templates鈹傗敎鈹€鈹€config.js#template閰嶇疆瑙h€︹攤鈹溾攢鈹€js-lib#presettemplate1鈹傗敂鈹€鈹€vue-component#presettemplate2鈹溾攢鈹€utils#Tools鐩綍鈹傗敂鈹€鈹€dir.jspackage.json{"name":"luckytiger-package-cli","version":"1.1.14","description":"package-cli","bin":{"lucky":"bin/lucky"},"scripts":{"lucky":"nodebin/lucky","bootstarp":"cnpmi&&cd./templates/js-lib/&&cnpmi&&cd../vue-component/&&cnpmi","dev:js-lib":"cdtemplates/js-lib&&npmrundev","dev:vue-component":"cdtemplates/vue-component&&npmrundev","dev:create":"rm-rftest-app&&nodebin/luckycreatetest-app","clear":"sudorm-rfnode_modules&&sudorm-rftemplates/js-lib/node_modules&&sudorm-rftemplates/vue-component/node_modules"},"author":"zhangzhengyi","license":"ISC","dependencies":{"chalk":"^2.4.2","commander":"^2.20.0","ejs":"^2.6.2","inquirer":"^6.4.1","validate-npm-package-name":"^3.0.0"}}閰嶇疆涓€浜涜剼鏈紝鏂逛究DEV妯℃澘鐨勬晥鏋滆繖鏍凤紝杩愯npmrundev:js-lib鏌ョ湅寮€鍙慾s-lib妯℃澘涓荤▼搴廱in/lucky#!/usr/bin/envnodeconstprogram=require('commander')program.version('0.0.1').usage('[options]')program.command('create').description('鍒涘缓涓€涓叏鏂扮殑npm缁勪欢妯″潡').action((name,cmd)=>{constoptions=cleanArgs(cmd)require('../lib/create')(name,options)})if(!process.argv.slice(2).length){program.outputHelp()}绋嬪簭銆俻arse(process.argv)//commander灏咰ommand瀵硅薄鏈韩浣滀负閫夐」浼犻€掞紝//浠呭皢瀹為檯閫夐」鎻愬彇鍒版柊瀵硅薄涓€俧unctioncleanArgs(cmd){constargs={}cmd.options.forEach(o=>{constkey=camelize(o.long.replace(/^--/,''))//濡傛灉涓€涓€夐」涓嶅瓨鍦ㄥ苟涓擟ommand鏈変竴涓悓鍚嶇殑鏂规硶//瀹冧笉搴旇琚鍒秈f(typeofcmd[key]!=='function'&&typeofcmd[key]!=='undefined'){args[key]=cmd[key]}})returnargs}杩欎釜鏂囦欢涓昏鏄熀鏈殑鍛戒护璁剧疆銆傜敤鎴疯皟鐢ㄤ簡鍒涘缓鍛戒护锛屽氨浼氳浆鍙戠粰lib/create.js澶勭悊涓诲垱寤哄櫒lib/cerate.jsconstpath=require('path')constinquirer=require('inquirer')constvalidateProjectName=require('validate-npm-package-name')constchalk=require('chalk')constcopy=require('./copy')constfs=require('fs')constdir=require('../utils/dir')consttemplates=require('../templates/config')asyncfunctioncreate(projectName,options){constcwd=options.cwd||process.cwd()constinCurrent=projectName==='.'甯搁噺鍚嶇О=inCurrent?path.relative('../',cwd):projectNameconsttargetDir=path.resolve(cwd,projectName||'.')constresult=validateProjectName(name)if(!result.validForNewPackages){console.error(chalk.red(`鏃犳晥鐨勯」鐩悕绉?"${name}"`))result.errors&&result.errors.forEach(err=>{console.error(chalk.red.dim('Error:'+err))})result.warnings&&result.warnings.forEach(warn=>{console.error(chalk.red.dim('璀﹀憡锛?+warn))})return}if(!dir.isDir(targetDir)){fs.mkdirSync(targetDir)}else{console.error(chalk.red(`姝ょ洰褰曚笅宸插瓨鍦ㄦ鏂囦欢澶癸紝璇峰垹闄ゆ垨淇敼椤圭洰name`))return}constanswers=awaitinquirer.prompt([{type:'list',name:'template',message:'template:璇烽€夋嫨椤圭洰妯℃澘',choices:templates.map((v,i)=>({key:i,name:v.name,value:v.dir}))},{type:'input',name:'author',message:'author:璇疯緭鍏ヤ綘鐨勫悕瀛?,楠岃瘉:function(value){return!!value}},{type:'input',name:'desc',message:'desc:璇疯緭鍏ラ」鐩弿杩?,validate:function(value){return!!value}},{type:'confirm',name:'confirm',message:'confirm:Finishedtheconfiguration?',default:false}])//寮€濮嬪鍒惰繃绋媍onstsourceDir=path.resolve(__dirname,'..','templates',answers.template)console.log(chalk.blue(`馃殌寮€濮嬪垱寤?..`))try{awaitcopy({from:sourceDir,to:targetDir,renderData:{desc:answers.desc,author:answers.author,name:projectName},ignore:['node_modules','package.json']})}catch(e){鎺у埗鍙?error(chalk.red(e))return}console.log(chalk.green('馃帀created!'))console.log()console.log(chalk.cyan(`$cd${projectName}`))console.log(chalk.cyan(`$npmi&&npmrundev`))}module.exports=create杩欓噷闇€瑕佸仛鍑犱欢浜嬫儏鏉ヤ繚璇侀」鐩悕绉板悎娉曠‘璁ら」鐩湪褰撳墠涓嶅瓨鍦╠irectory鏀堕泦鐢ㄦ埛濉啓鐨勪俊鎭疭tart鍦ㄥ鍒惰繃绋嬩腑锛宑halk搴撳彲浠ヨ緭鍑哄僵鑹插懡浠よ锛屾洿鍔犵編瑙傘€傛垜鎶婃ā鏉跨殑涓€浜涢厤缃俊鎭斁鍒皌emplates/config.js涓紝鐩殑鏄В鑰?/templates/config.jsmodule.exports=[{name:'JavaScriptLibrary-suitforcommonJSlibraries',dir:'js-lib'},{name:'Vue-components-forVuecomponentlibrary',dir:'vue-component'}]鎺ヤ笅鏉ョ湅澶嶅埗杩囩▼copylib/copyconstfs=require('fs')constpath=require('path')constdir=require('../utils/dir')constejs=require('ejs')asyncfunctioncopy({from,to,renderData,ignore=[]}){letfiles=fs.readdirSync(from)//鍖哄垎鏂囦欢鍜岀洰褰昹etrFiles=[]letdirs=[]for(constfileNameoffiles){if(dir.isDir(path.resolve(from,fileName))){dirs.push(fileName)}else{rFiles.push(fileName)}}//澶嶅埗骞剁紪璇戞枃浠秗Files.forEach(fileName=>{//闇€瑕佸拷鐣f(ignore.some(v=>v===fileName)){return}letcontent=fs.readFileSync(path.resolve(from,fileName),'utf-8')//杩欎釜鏂囦欢闇€瑕佽皟鐢╡js妯℃澘寮曟搸缂栬瘧if(/ejs$/.test(fileName)){content=ejs.render(content,renderData)fileName=fileName.replace('.ejs','')}fs.writeFileSync(path.resolve(to,fileName),content)})//閫掑綊澶嶅埗鐩綍dirs.forEach(dirName=>{//闇€瑕佸拷鐣ュ鏋?ignore.some(v=>v===dirName)){return}constfromDir=path.resolve(from,dirName)consttoDir=path.resolve(to,dirName)if(!dir.isDir(toDir)){fs.mkdirSync(toDir)}copy({from:fromDir,to:toDir,renderData,ignore})})}module.exports=copycopy鏄竴涓€掑綊澶嶅埗鏂囦欢鍜岀洰褰曠殑缁撴瀯锛屾繁搴︿紭鍏堬紝浠栨湁鍥涗釜鍙傛暟婧愭枃浠跺す銆佺洰鏍囨枃浠跺す銆佹覆鏌撴暟鎹€佸拷鐣ュ垪琛ㄣ€傛垜浠殑妯℃澘瀹為檯涓婇渶瑕佽兘澶熸寜闇€鍛堢幇鍐呭銆傛瘮濡傜敓鎴愮殑package.json搴旇鏈夌敤鎴峰湪鍒涘缓鏃跺~鍐欑殑椤圭洰鍚嶇О銆佸垱寤鸿€呫€佹弿杩扮瓑淇℃伅銆傛墍浠ユ垜杩欓噷浣跨敤EJS妯℃澘寮曟搸杩涜娓叉煋銆傛墍鏈変互.ejs缁撳熬鐨勬枃浠堕兘浼氱粡杩囧紩鎿?娓叉煋鏁版嵁娓叉煋锛岀劧鍚庤緭鍑恒€傛瘮濡俻ackage.json.ejs鍋氫簡涓€浜涜蹇借鐨勮璁°€傚師鍥犳槸杩欎簺鏂囦欢鍦ㄥ紑鍙戞ā鏉跨殑杩囩▼涓渶瑕侊紝鐪熸鐢熸垚鐨勬椂鍊欓渶瑕佽繃婊ゃ€傚叏閮ㄤ娇鐢ㄥ悓姝PI锛屽洜涓烘垜浠殑鏂囦欢姣旇緝灏忥紝娌℃湁鍦ㄦ湇鍔$浣跨敤锛屾墍浠ラ樆濉炴槸娌℃湁闂鐨勩€傛ā鏉挎惌寤烘垜杩欓噷璁捐浜嗕袱涓璁炬ā鏉匡紝涓€涓槸Vue-component缁勪欢搴撴ā鏉匡紝涓€涓槸JS搴撴ā鏉匡紙渚嬪瓙涔熸槸鍩轰簬Vue鐨勶級銆傚鏋滀綘鏈夌被浼肩殑闇€姹傦紝鍙互鍘荤湅鐪嬨€傝繖涓や釜妯℃澘鏄厛鐢╲ue-cli3.0鐢熸垚鐒跺悗淇敼鐨勩€備慨鏀圭殑鐩殑鏄负浜嗘洿濂界殑婊¤冻缁勪欢搴撶殑闇€姹傘€備笌鏅€氶」鐩笉鍚岋紝缁勪欢搴撻渶瑕佸湪DEV妯″紡涓嬫祴璇曞拰寮€鍙戠粍浠讹紝鐒跺悗蹇呴』鍏峰鍗曠嫭鎵撳寘杩欎釜缁勪欢锛岀劧鍚庡彂甯冪殑鑳藉姏銆傚叿浣撳彲浠ョ洿鎺ョ湅浠g爜鏋勫缓杩囩▼涓殑涓€浜涘潙銆傞渶瑕佹敞鎰忕殑鏄ā鏉块噷闈㈠簲璇ユ湁涓や釜package.json鏂囦欢銆俻ackage.json鐢ㄤ簬妯℃澘鐨凞EV妯″紡銆傛枃浠跺彂甯冪櫧鍚嶅崟涓娇鐢ㄤ簡files瀛楁锛屼細瀵艰嚧浣犵殑cli宸ュ叿鏃犳硶鍙戝竷鏁翠釜妯℃澘锛堣繖搴旇鏄洜涓烘ā鏉块噷闈㈢殑package.json鍜屾暣涓猚li宸ュ叿鐨刾ackage.json鏈夐噸鍙犲叧绯?.鍦ㄦā鏉垮唴鐨?gitignore鏂囦欢涓坊鍔?ejs鏃讹紝鍚屾牱浣跨敤clipublish鏃讹紝妯℃澘涓殑.gitignore鏂囦欢鏃犳硶姝e父涓婁紶锛屾墍浠ユ坊鍔犱竴涓猠js鍙互浣垮叾浼鎴愭櫘閫氭枃浠躲€傛墍浠ユ垜瑙夊緱npm鍖呯殑宓屽澶鏄撳共鎵颁簡涓€鐐广€傚缓璁ぇ瀹跺啓缁勪欢搴撶殑鏃跺€欐墜鍐橳S绫诲瀷澹版槑绫诲瀷锛屽湪VSCode涓嬪彲浠ュ緱鍒板緢濂界殑浠g爜鎻愮ず鏁堟灉銆傞鍏堥渶瑕佸湪缁勪欢搴撶殑package.json涓坊鍔犱竴涓睘鎬"typings":"types/index.d.ts",}銆傝繖閲屾垜鍐欎簡涓€涓畝鍗曠殑鍑芥暟//Finallyexportexportdefault{say(name){return`yourname:${name}`}}//index.d.tsfunctionsay(name:String):Stringexportdefault{say}so褰撴偍浣跨敤姝ゆā鍧楁椂锛孷SCode鍙互涓烘偍鎻愪緵鏇村己澶х殑鎻愮ず銆傝繖鏄竴涓澶栫殑鎻愰啋銆傜粡杩囨垜鐨勭爺绌讹紝element-ui绛夌粍浠跺簱鏄彲浠ユ湁props鎻愮ず鐨勶紝鍥犱负鏄笓闂ㄤ负vetur缁勪欢寮€鍚庨棬鐨勩€傚啓绫诲瀷鍙兘鏈塉S绾у埆鐨勬彁绀恒€傚啓鐨勬椂鍊橵ue-template杩樻槸涓嶈锛屾湡寰呬互鍚庣殑鏀寔銆傚弬鑰僾ue-cliVuecli3搴撴柟寮忔惌寤虹粍浠跺簱鍙戝竷鍒皀pmprocesselement-ui鎴戠殑涓汉鍗氬