自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從零實現(xiàn)命令行腳手架工具——自動初始化項目工程以及發(fā)布到NPM

開發(fā) 開發(fā)工具
這篇文章將帶你從零實現(xiàn)一款命令行腳手架工具用于初始化項目以及如何發(fā)布到NPM。那么,這么方便的命令行工具是怎么實現(xiàn)的呢?下面我們就開始進入實戰(zhàn)環(huán)節(jié)。

[[418135]]

前言

這篇文章將帶你從零實現(xiàn)一款命令行腳手架工具用于初始化項目以及如何發(fā)布到NPM。首先,我們所熟知的VueCLI就是采用命令行工具快速生成項目工程目錄的,這樣,我們每次開發(fā)項目前只需要在命令行中輸入命令,然后就可以快速生成項目工程,非常方便。那么,這么方便的命令行工具是怎么實現(xiàn)的呢?下面我們就開始進入實戰(zhàn)環(huán)節(jié)。

實戰(zhàn)

我將會使用之前自己開發(fā)的一款腳手架工具strview-cli來介紹如何實現(xiàn)它的。這個腳手架工具的源碼地址如下:

  1. https://github.com/maomincoding/strview-cli 

第一步

首先,我們姑且創(chuàng)建一個文件夾名字叫strviewCli。

  1. mkdir strviewCli 

然后,在文件夾中初始化項目

  1. npm init 

之后,自動生成一個package.json文件。

第二步

我們再創(chuàng)建一個文件夾,即bin。

  1. mkdir bin 

接著,在文件夾中我們創(chuàng)建一個index.js文件、config文件夾、utils文件夾。

  1. touch index.js 
  2. mkdir config 
  3. mkdir utils 

最后,在config 文件中創(chuàng)建一個index.js文件,在utils文件夾中創(chuàng)建一個checkDire.js。

  1. touch index.js 
  2. touch checkDire.js 

目前,我們文件目錄結(jié)構(gòu)為

  1. - bin 
  2.  -- config 
  3.   --- index.js 
  4.  -- utils 
  5.   --- checkDire.js 
  6.  -- index.js 
  7. - package.json 

最后的最后,我們在根目錄下,創(chuàng)建一個.gitignore文件,以及README.md。

最后,命令行工具項目文件目錄如下:

  1. - bin 
  2.  -- config 
  3.   --- index.js 
  4.  -- utils 
  5.   --- checkDire.js 
  6.  -- index.js 
  7. - package.json 
  8. - README.md 
  9. - .gitignore 

第三步

上面兩步,我們給我們的命令行工具奠定了基本結(jié)構(gòu)。下面,我們將在一一為每個文件注入靈魂~

首先,.gitignore文件和README.md,這里就不過多闡述了,可以根據(jù)自己的需要進行增添內(nèi)容。

其次,詳細介紹的就是package.json文件。以下是我自己寫的package.json,這里需要注意幾個重要的字段。

  • name :項目名
  • version:版本號
  • description:項目描述
  • main:入口文件
  • author:作者
  • keywords:關(guān)鍵詞
  • bin:腳本執(zhí)行入口
  • repository:代碼倉庫
  • license:許可證
  • private:私有
  • dependencies:依賴
  • browserslist:指定了項目的目標瀏覽器的范圍
  1.   "name""strview-cli"
  2.   "version""1.1.1"
  3.   "description""Strview.js project scaffolding tools."
  4.   "main""index.js"
  5.   "author": { 
  6.   "name""maomincoding"
  7.   "email""17864296568@163.com"
  8.   "url""https://www.maomin.club" 
  9.    }, 
  10.   "keywords": [ 
  11.  "strview"
  12.     "strview.js"
  13.     "strview-app"
  14.     "strview-cli" 
  15.  ], 
  16.   "bin": { 
  17.   "strview-cli""./bin/index.js" 
  18.  }, 
  19.   "repository": { 
  20.   "type""git"
  21.   "url""https://github.com/maomincoding/strview-cli.git" 
  22.  }, 
  23.   "license""MIT"
  24.   "private"false
  25.   "dependencies": { 
  26.   "chalk""^4.0.0"
  27.   "commander""^5.0.0"
  28.   "fs-extra""^9.0.0"
  29.   "inquirer""^7.1.0" 
  30.     }, 
  31.  "browserslist": [ 
  32.   "> 1%"
  33.   "last 2 versions" 
  34.  ] 

上面的package.json中幾個屬性如:name、version、description、main、author、keywords、repository、license可以根據(jù)自己的需求來定義。

你可能會看到dependencies屬性中有幾個依賴,分別是chalk、commander、fs-extra、inquirer。這里先提一下,下面會詳細介紹它們。不過,需要注意的是fs-extra模塊是添加了本機fs模塊中不包含的文件系統(tǒng)方法,并向fs方法添加了promise支持。它還使用優(yōu)美的fs來防止EMFILE錯誤。它應(yīng)該是fs的替代品。

第四步

接下來,我們將進入bin文件夾中,然后,我們首先需要編輯config\index.js文件。

  1. module.exports = { 
  2.  npmUrl: 'https://registry.npmjs.org/strview-cli'
  3.  promptTypeList: [ 
  4.   { 
  5.    type: 'list'
  6.    message: 'Please select the template type to pull:'
  7.    name'type'
  8.    choices: [ 
  9.     { 
  10.      name'strview-app'
  11.      value: { 
  12.       url: 'https://github.com/maomincoding/strview-app.git'
  13.       gitName: 'strview-app'
  14.       val: 'strview-app'
  15.      }, 
  16.     }, 
  17.    ], 
  18.   }, 
  19.  ], 
  20. }; 

以上代碼中導(dǎo)出一個對象,對象中有兩個屬性:npmUrl和promptTypeList。

npmUrl屬性是命令行工具提交到NPM的地址。怎么得到這個地址呢?你需要按照下面步驟:

登錄NPM

  1. npm login 

依次輸入你的用戶名、密碼、郵箱。

發(fā)布到NPM

  1. npm publish 

發(fā)布成功后,會顯示版本號。記住,每次發(fā)布都要更改版本號,否則會出錯。

正常發(fā)布之后,你可以打開NPM網(wǎng)址,搜索你的命令行工具的名稱。比如我的命令行工具strview-cli。網(wǎng)址即:https://registry.npmjs.org/strview-cli。

promptTypeList屬性中有一個choices屬性,它是一個數(shù)組,你可以配置你遠程項目工程倉庫。數(shù)組每個元素是一個對象,比如這里的

  1.  name'strview-app'
  2.  value: { 
  3.    url: 'https://github.com/maomincoding/strview-app.git'
  4.    gitName: 'strview-app'
  5.    val: 'strview-app'
  6.   }, 

name屬性是你的項目工程名稱,value屬性又是一個對象,里面有三個屬性:url、gitName、val分別表示遠程倉庫地址、倉庫名、值(一般與倉庫名一致)。你可以根據(jù)你的需要進行配置,這里是我配置的自己的strview-app。

以上就是config\index.js文件的配置。

第五步

下面,我們還在bin文件夾中,我們接下來編輯utils\checkDire.js文件。

  1. const fs = require("fs"); 
  2. const chalk = require("chalk"); 
  3.  
  4. module.exports = function (dir, name) { 
  5.   let isExists = fs.existsSync(dir); 
  6.   if (isExists) { 
  7.     console.log( 
  8.       chalk.red( 
  9.         `The ${name} project already exists in  directory. Please try to use another projectName` 
  10.       ) 
  11.     ); 
  12.     process.exit(1); 
  13.   } 
  14. }; 

這個文件沒有自定義的部分,你只需要直接用即可。這里我們看到引入兩個模塊,分別是fs、chalk。Node.js內(nèi)置的fs模塊就是文件系統(tǒng)模塊,負責(zé)讀寫文件。chalk模塊是美化命令行輸出樣式,使輸出命令不再單調(diào)。

我們看到這里導(dǎo)出一個函數(shù),函數(shù)有兩個參數(shù):分別是dir和name。我們這里先暫且不看這個函數(shù),先只知道需要傳兩個參數(shù)就可以。

第六步

下面我們先分析bin\index.js文件,這個文件是命令行工具的入口文件,非常重要。同樣,這里不需要自定義,直接用就可以。

  1. #!/usr/bin/env node 
  2.  
  3. const fs = require('fs'); 
  4. const path = require('path'); 
  5. const chalk = require('chalk'); 
  6. const commander = require('commander'); 
  7. const inquirer = require('inquirer'); 
  8. const checkDire = require('./utils/checkDire.js'); 
  9. const { exec } = require('child_process'); 
  10. const { version } = require('../package.json'); 
  11. const { promptTypeList } = require('./config'); 
  12.  
  13. commander 
  14.  .version(version, '-v, --version'
  15.  .command('init <projectName>'
  16.  .alias('i'
  17.  .description('Enter the project name and initialize the project template'
  18.  .action(async (projectName) => { 
  19.   await checkDire(path.join(process.cwd(), projectName), projectName); 
  20.   inquirer.prompt(promptTypeList).then((result) => { 
  21.    const { url, gitName, val } = result.type; 
  22.    console.log( 
  23.     'The template type information you selected is as follows:' + val 
  24.    ); 
  25.    console.log('Project initialization copy acquisition...'); 
  26.    if (!url) { 
  27.     console.log( 
  28.      chalk.red(`${val} This type is not supported at the moment...`) 
  29.     ); 
  30.     process.exit(1); 
  31.    } 
  32.    exec('git clone ' + url, function (error, stdout, stderr) { 
  33.     if (error !== null) { 
  34.      console.log(chalk.red(`clone fail,${error}`)); 
  35.      return
  36.     } 
  37.     fs.rename(gitName, projectName, (err) => { 
  38.      if (err) { 
  39.       exec('rm -rf ' + gitName, function (err, out) { }); 
  40.       console.log( 
  41.        chalk.red(`The ${projectName} project template already exist`) 
  42.       ); 
  43.      } else { 
  44.       if (fs.existsSync(`./${projectName}/.git/config`)) { 
  45.        exec('git remote rm origin', { cwd: `./${projectName}` }); 
  46.        console.log( 
  47.         chalk.green( 
  48.          `✔ The ${projectName} project template successfully create
  49.         ) 
  50.        ); 
  51.       } 
  52.      } 
  53.     }); 
  54.    }); 
  55.   }); 
  56.  }); 
  57.  
  58. commander.parse(process.argv); 

我們從頭開始看,我們會看到引入了fs、path、chalk、commander、inquirer、child_process。

path 模塊提供了用于處理文件和目錄的路徑的實用工具。

commander是完整的 node.js 命令行解決方案,它有很多用法,具體你可以參照Commander中文文檔:

  1. https://github.com/tj/commander.js/blob/master/Readme_zh-CN.md 

inquirer是通用交互式命令行用戶界面的集合。開始通過npm init創(chuàng)建package.json文件的時候就有大量與用戶的交互,而現(xiàn)在大多數(shù)工程都是通過腳手架來創(chuàng)建的,使用腳手架的時候最明顯的就是與命令行的交互,如果想自己做一個腳手架或者在某些時候要與用戶進行交互,這個時候就不得不提到inquirer.js了。

child_process模塊是nodejs的一個子進程模塊,可以用來創(chuàng)建一個子進程,并執(zhí)行一些任務(wù)。比如說就可以直接在js里面調(diào)用shell命令。

介紹完引入的模塊,然后再介紹下面的代碼。你會看到下面的代碼大部分都用到了commander的方法。

首先,commander.version(version, '-v, --version'),.version()方法可以設(shè)置版本,之后就可以使用-v或--version命令查看版本。

通過 .command('init ') 可以配置命令。這里的意思是初始化你的項目名稱,你可以根據(jù)自己的需求設(shè)置。也可以使用.alias('i')簡寫初始化配置命令,原來npm init ,現(xiàn)在也可以使用npm i 命令。

.description('Enter the project name and initialize the project template')這行代碼中.description方法則是對上面初始化配置項目名的描述。

.action((projectName, cmd) => {...})這行代碼中.action方法是定義命令的回調(diào)函數(shù),我們發(fā)現(xiàn)它使用了async/await這組關(guān)鍵字用來處理異步。首先,await checkDire(path.join(process.cwd(), projectName), projectName);傳入兩個參數(shù)分別為項目所在的目錄、項目名稱。我們這里先分析checkDire方法,也就是之前utils\checkDire.js文件內(nèi)的方法。

  1. module.exports = function (dir, name) { 
  2.   let isExists = fs.existsSync(dir); 
  3.   if (isExists) { 
  4.     console.log( 
  5.       chalk.red( 
  6.         `The ${name} project already exists in  directory. Please try to use another projectName` 
  7.       ) 
  8.     ); 
  9.     process.exit(1); 
  10.   } 
  11. }; 

fs.existsSync(dir)以同步的方法檢測目錄是否存在。如果目錄存在 返回 true ,如果目錄不存在 返回false。如果存在了,就執(zhí)行下面的提示并退出終止進程。

接著,我們又回到bin\index.js文件。接著往下執(zhí)行,到了inquirer.prompt()這個方法,這個方法的作用主要是啟動提示界面(查詢會話),第一個參數(shù)是包含問題對象的問題(數(shù)組)(使用反應(yīng)式接口,還可以傳遞一個Rx.Observable實例),這里我們傳入的是config\index.js文件中的promptTypeList屬性,它是一個數(shù)組。

  1. promptTypeList: [ 
  2.  { 
  3.   type: 'list'
  4.   message: 'Please select the template type to pull:'
  5.   name'type'
  6.   choices: [ 
  7.    { 
  8.     name'strview-app'
  9.     value: { 
  10.      url: 'https://github.com/maomincoding/strview-app.git'
  11.      gitName: 'strview-app'
  12.      val: 'strview-app'
  13.     }, 
  14.    }, 
  15.   ], 
  16.  }, 
  17. ], 

inquirer.prompt()這個方法返回一個Promise對象,所以這里可以then()方法來獲取返回的數(shù)據(jù)。然后我們通過解構(gòu)來分別獲取到url、gitName、val這三個屬性值。

  1. const { url, gitName, val } = result.type; 

然后,下面就是輸出命令以及執(zhí)行命令的環(huán)節(jié)了。我分為兩部分來分析剩余代碼,第一部分如下:

  1. console.log('The template type information you selected is as follows:' + val); 
  2. console.log('Project initialization copy acquisition...'); 
  3.  
  4. if (!url) { 
  5.  console.log(chalk.red(`${val} This type is not supported at the moment...`)); 
  6.  process.exit(1); 

我們這里有一個判斷語句,就是判斷遠程倉庫地址是否是假值,如果是假值的話,就執(zhí)行提示并退出終止進程。

接著,我們分析第二部分:

  1. exec('git clone ' + url, function (error, stdout, stderr) { 
  2.  if (error !== null) { 
  3.   console.log(chalk.red(`clone fail,${error}`)); 
  4.   return
  5.  } 
  6.  fs.rename(gitName, projectName, (err) => { 
  7.   if (err) { 
  8.    exec('rm -rf ' + gitName, function (err, out) { }); 
  9.    console.log(chalk.red(`The ${projectName} project template already exist`)); 
  10.   } else { 
  11.    if (fs.existsSync(`./${projectName}/.git/config`)) { 
  12.     exec('git remote rm origin', { cwd: `./${projectName}` }); 
  13.     console.log( 
  14.      chalk.green(`✔ The ${projectName} project template successfully create`) 
  15.     ); 
  16.    } 
  17.    } 
  18.  }); 

這部分主要是執(zhí)行命令,也是最關(guān)鍵的部分。這部分首先使用了exec()方法,第一個參數(shù)是要執(zhí)行的命令,第二個參數(shù)是回調(diào)函數(shù)。

首先,我們執(zhí)行exec('git clone ' + url)來下載遠程項目,接著我們進入回調(diào)函數(shù),如果有錯誤,就輸出提示并退出。否則,將使用fs.rename()方法將文件重命名。因為我們下載的遠程倉庫名不一定跟我們初始化配置的名字一樣。

如果錯誤,就刪除遠程項目工程目錄。否則,就判斷./${projectName}/.git/config文件是否存在,如果存在就執(zhí)行exec('git remote rm origin', { cwd:./${projectName}});命令刪除遠程倉庫地址。這是因為需要自定義配置倉庫地址,而不是直接使用下載的倉庫地址。最后,提示創(chuàng)建成功。

最后一行。commander.parse(process.argv);這行代碼中.parse()的第一個參數(shù)是要解析的字符串數(shù)組,也可以省略參數(shù)而使用process.argv。指明,按 node 約定。

第七步

到了這一步,所有配置文件都配置完成了。如果你想開源的話,你可以參照線上自己生成一個LICENSE文件。這個文件是軟件許可證,可以去github去自動生成這個文件。

最后,我們就要發(fā)布我們這個命令行工具了。注意,在發(fā)布之前,需要改一下你的版本號。 如之前是1.0.0,現(xiàn)在可以改成2.0.0。具體這三個數(shù)字怎么定義,也有說法。第一部分為主版本號,變化了表示有了一個不兼容上個版本的大更改。第二部分為次版本號,變化了表示增加了新功能,并且可以向后兼容。第三部分為修訂版本號,變化了表示有bug修復(fù),并且可以向后兼容。

  1. npm publish 

發(fā)布成功。

第八步

這里以strview-cli為例。

你可以全局安裝你的腳手架。

  1. npm i strview-cli -g 

安裝完成之后,你可以查看版本。

  1. strview-cli -v 

最后,就是初始化項目了, 是自定義項目名稱。  

  1. strview-cli init <projectName> 

or 

  1. strview-cli i <projectName> 

結(jié)語

謝謝閱讀,希望沒有耽誤你的時間。

你可以自己封裝一個常用的項目工程,可以通過這種方式來初始化你的項目。這樣,才會顯得有逼格!!!哈哈哈~

本文轉(zhuǎn)載自微信公眾號「前端歷劫之路」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系前端歷劫之路公眾號。

 

責(zé)任編輯:武曉燕 來源: 前端歷劫之路
相關(guān)推薦

2021-12-19 07:22:16

Create前端工具

2021-04-28 16:10:48

開發(fā)腳手架 Spring

2021-05-13 17:02:38

MDC腳手架日志

2020-08-19 08:55:47

Redis緩存數(shù)據(jù)庫

2022-04-24 11:33:47

代碼管理工程

2021-05-21 05:22:52

腳手架工具項目

2021-11-08 09:35:09

Vue代碼前端

2021-09-01 10:07:43

開發(fā)零搭建Groovy

2016-08-10 14:59:41

前端Javascript工具

2019-06-10 15:00:27

node命令行前端

2021-04-13 14:47:53

認證授權(quán)Java

2021-07-13 18:42:38

Spring Boot腳手架開發(fā)

2021-03-09 17:11:09

數(shù)據(jù)庫腳手架開發(fā)

2020-12-10 16:16:08

工具代碼開發(fā)

2020-12-11 06:44:16

命令行工具開發(fā)

2017-07-21 09:56:46

Webpack3 Vue.js腳手架

2021-04-20 19:24:16

腳手架 Java微信

2021-12-23 10:35:32

SpringCloud腳手架架構(gòu)

2020-06-29 11:35:02

Spring BootJava腳手架

2021-01-07 05:34:07

腳手架JDK緩存
點贊
收藏

51CTO技術(shù)棧公眾號