Node.js 新手的 cli 工具開(kāi)發(fā)初體驗(yàn) - 項(xiàng)目目錄管理工具 yuki

技術(shù)的學(xué)習(xí)一定要輔以代碼的實(shí)踐,菜鳥(niǎo)程序員撲在輪子上要像饑餓的人撲在面包上。
——沃茲基碩德

受到掘金上看到的 yddict:一個(gè)命令行查單詞的工具 的啟發(fā),原來(lái)摸一個(gè) Node.js 的 demo 不一定非要寫(xiě)一個(gè)服務(wù)器。恰逢最近開(kāi)始看《算法(第4版)》,把練習(xí)代碼和筆記傳到 github 上時(shí)需要在 README.md 里放一份帶鏈接的目錄,方便在線跳轉(zhuǎn)查閱。兩者綜合,就有了開(kāi)發(fā)一個(gè)能夠?qū)㈨?xiàng)目?jī)?nèi)文件結(jié)構(gòu)自動(dòng)映射并生成為 README.md 的項(xiàng)目目錄管理工具的靈感。

看上去是一個(gè)簡(jiǎn)單的小工具,實(shí)際上花了 3 天才基本成型(當(dāng)然不是整的)。隨著思路從項(xiàng)目目錄管理到圖書(shū)管理再到書(shū)籍再到文藝社,我決定將這個(gè)小工具命名為 yuki,蘊(yùn)含了我個(gè)人滿滿的宅趣味。

命名由來(lái)-長(zhǎng)門(mén)大萌神

幸運(yùn)的是,這個(gè)日語(yǔ)里常見(jiàn)的詞竟然在 NPM 里還沒(méi)被搶用。我也因此不用為其加個(gè)后綴,直接就可以用這個(gè)名字傳上 NPM,以供使用。

這篇文章剩下來(lái)的篇幅一是介紹這個(gè)小工具的使用場(chǎng)景、實(shí)際用法等,二是大概談一談開(kāi)發(fā)過(guò)程中稍微值得一記的經(jīng)驗(yàn)。

關(guān)于 yuki

使用 Node.js 開(kāi)發(fā)的項(xiàng)目目錄管理工具,能夠?qū)㈨?xiàng)目?jī)?nèi)文件結(jié)構(gòu)自動(dòng)映射并生成為 README.md

example.gif

項(xiàng)目地址

bighuang624/yuki

適用場(chǎng)合

當(dāng)一份 README.md 的主體內(nèi)容是項(xiàng)目目錄,而你又厭倦了每次增加、修改、刪除項(xiàng)目中文件時(shí)都要對(duì) README 進(jìn)行維護(hù),那么不妨試試 yuki!

它可以在極短時(shí)間內(nèi)幫你生成符合要求的 README.md 文檔。你更可以通過(guò)配置一份 yuki.config.json 來(lái)滿足你的以下需求:

  • 固定文檔標(biāo)題
  • 目錄前后增加固定內(nèi)容
  • 映射時(shí)忽略指定文件夾、文件、擴(kuò)展名
  • 根據(jù)指定擴(kuò)展名選擇是否去掉文件名的擴(kuò)展名或加上書(shū)名號(hào)
  • 讓每個(gè)文件都帶上 Github 的鏈接以方便在線跳轉(zhuǎn)查看

你可以用 yuki 幫助你輕松維護(hù) github 上類(lèi)似博客、筆記、代碼匯總等項(xiàng)目!

效果示例

我的《算法》筆記及代碼項(xiàng)目的 README.md 完全通過(guò) yuki 生成。你可以點(diǎn)擊以查看效果。

使用方法

請(qǐng)確認(rèn)你使用的電腦有 Node 環(huán)境,越新越好。

安裝 yuki

npm install -g yuki

進(jìn)入需要生成 README.md 的文件夾

# 請(qǐng)將 <dirname> 換為文件夾路徑
cd <dirname>

創(chuàng)建 yuki.config.json(可選)

touch yuki.config.json

配置 yuki.config.json(可選)

{
  // README.md的大標(biāo)題(h1),默認(rèn)為所在文件夾名
  "title": "《算法(第4版)》筆記及代碼",
  // github庫(kù)地址,如果配置了這項(xiàng)會(huì)給每個(gè)文件加上超鏈接
  // 如果配置,請(qǐng)保證index填寫(xiě)無(wú)誤,且所有文件名不含空格(否則鏈接無(wú)法正確表示)
  // branch默認(rèn)為master
  "repository": {
    "index": "https://github.com/bighuang624/Algorithms-notes",
    "branch": "master"
  },
  // 目錄開(kāi)始的標(biāo)題等級(jí)
  // 默認(rèn)為2,即該目錄下的文件夾名等級(jí)從3開(kāi)始,隨層級(jí)深入遞減
  "startLevel": 2,
  // 需要忽略的目錄、擴(kuò)展名和文件,都以數(shù)組表示
  "ignore": {
    "dir": [".git"],
    "extname": [".json"],
    "file": [
      "yuki.config.json",
      ".gitignore",
      "README.md",
      ".DS_Store"
    ]
  },
  // 根據(jù)擴(kuò)展名選擇對(duì)展示的文件名做一些處理
  // 每個(gè)擴(kuò)展名的配置需要單獨(dú)一個(gè)對(duì)象
  // 目前支持省略擴(kuò)展名"withoutExt": true
  // 和加上書(shū)名號(hào)"withBookmark": true
  "format": [
    {
      "extname": ".md",
      "withoutExt": true,
      "withBookmark": true
    }
  ],
  // 在大標(biāo)題之后,目錄之前添加的內(nèi)容
  // 每個(gè)對(duì)象可選擇包含標(biāo)題、標(biāo)題等級(jí)和內(nèi)容
  // 其中,標(biāo)題和標(biāo)題等級(jí)需在一個(gè)對(duì)象中一同填寫(xiě)
  "prefix": [
    {
      "content": "[![](https:\//img.shields.io\/badge/%E4%BD%9C%E8%80%85-KyonHuang-7AD6FD.svg)](http:\//kyonhuang.top)"
    }, {
      "title": "目錄",
      "level": "2"
    }
  ],
  // 在README.md末尾添加的內(nèi)容
  // 和prefix相同,每個(gè)對(duì)象可選擇包含標(biāo)題、標(biāo)題等級(jí)和內(nèi)容
  "append": [
    {
      "title": "維護(hù)",
      "level": "2",
      "content": "本文檔由 [yuki](https://github.com/bighuang624/yuki) 維護(hù)"
    }
  ]
}

因?yàn)?JSON 標(biāo)準(zhǔn)中不含注釋?zhuān)?qǐng)?jiān)谑褂脮r(shí)將注釋去掉。項(xiàng)目中也提供一份不帶注釋、可供修改使用的 yuki.config.json 模版。

不需要的配置選項(xiàng)請(qǐng)全部刪除。

創(chuàng)建 README.md

yuki

LICENSE

Apache License 2.0

開(kāi)發(fā)中的那些事

Cli 命令工具開(kāi)發(fā)的準(zhǔn)備工作

我們來(lái)了解一下圍繞 NPM 開(kāi)發(fā)的準(zhǔn)備工作。第一步自然是在文件夾下使用命令npm init生成 package.json 文件。

注冊(cè)

可以通過(guò)以下命令在 NPM 資源庫(kù)中注冊(cè)用戶:

npm adduser

之后跟著要求填寫(xiě) Username、Password、Email 就 ok 了。項(xiàng)目發(fā)布前可能需要npm login一下。

版本號(hào)

NPM 使用語(yǔ)義版本號(hào)來(lái)管理代碼。語(yǔ)義版本號(hào)分為 X.Y.Z 三位,分別代表主版本號(hào)、次版本號(hào)和補(bǔ)丁版本號(hào)。當(dāng)代碼變更時(shí),版本號(hào)按以下原則更新:

  • 如果只是修復(fù) bug,需要更新 Z 位。
  • 如果是新增了功能,但是向下兼容,需要更新 Y 位。
  • 如果有大變動(dòng),向下不兼容,需要更新 X 位。

當(dāng)然我這個(gè)小項(xiàng)目比較隨便,bug 修的多了次版本號(hào)看心情也往上升一次。

你可以用npm view <pkg> version來(lái)查看你發(fā)布到 NPM 項(xiàng)目的現(xiàn)在版本號(hào)。

測(cè)試小竅門(mén)

這兩個(gè)小竅門(mén)可以節(jié)省你在一邊開(kāi)發(fā)一邊測(cè)試的時(shí)間(沒(méi)發(fā)現(xiàn)之前,3 天的開(kāi)發(fā)時(shí)間花在這上面的不少...)。

  • 在 package.json 所在目錄下使用npm install . -g可先在本地安裝當(dāng)前命令行程序,可用于發(fā)布前的本地測(cè)試。

  • 使用npm update <pkg> -g可以把全局安裝的對(duì)應(yīng)命令行程序更新至最新版。

編寫(xiě)

想要在全局使用你編寫(xiě)的 cli 工具,你需要在 package.json 加一個(gè) bin 屬性:

"bin": {
  "yuki": "./index.js"
},

yuki 換做你啟動(dòng)這個(gè)程序所要在命令行輸入的命令。屬性的值是項(xiàng)目的入口文件。添加這個(gè)屬性后,在命令行執(zhí)行yuki就等同于執(zhí)行node ./index.js。

發(fā)布項(xiàng)目

項(xiàng)目寫(xiě)了一個(gè)版本準(zhǔn)備發(fā)布,先在 package.json 所在目錄下用npm version看一下版本號(hào),然后就可以 publish 了。

cd yuki
npm version
npm publish

之后就可以通過(guò)全局安裝來(lái)使用:

npm i -g yuki

獲得程序運(yùn)行的路徑

說(shuō)實(shí)話,一個(gè)我很不擅長(zhǎng)的東西就是 API,哪怕是那些非常常用的。這次我一開(kāi)始就遇到了麻煩:如何獲得程序開(kāi)始遍歷的“根目錄”路徑?

在查找的同時(shí)順便了解了一下獲得各種路徑的方法,有以下幾種:

  • process.cwd()獲得 Node.js 進(jìn)程當(dāng)前工作的路徑(即執(zhí)行命令行時(shí)候的路徑,而非代碼路徑。例如在根目錄下執(zhí)行node ./xxx/xxx/example.js,則process.cwd()返回的是根目錄地址);

  • __dirname: 獲得代碼存放的位置(例如運(yùn)行位于/usr/a目錄下的example.js文件:node example.js,則__dirname返回/usr/a);

  • process.execPath: 返回返回啟動(dòng) Node.js 進(jìn)程的可執(zhí)行文件所在的絕對(duì)路徑(也就是當(dāng)前執(zhí)行的 Node 自身的路徑,例如:/usr/local/bin/node)。

根據(jù)查詢結(jié)果和實(shí)際需求,應(yīng)該使用process.cwd()(我們要求在 package.json 所在目錄下使用 yuki)。不過(guò)實(shí)際上使用的是path.resolve()path.resolve()不含參數(shù)時(shí),返回返回當(dāng)前工作目錄的絕對(duì)路徑,也符合要求。

yuki 的編寫(xiě)也幫助我熟悉了 Node 里的很多 API,尤其是和 path 和 fs 相關(guān)的。

先遍歷文件再深度遍歷文件夾

開(kāi)發(fā)的過(guò)程中發(fā)現(xiàn)一個(gè)問(wèn)題:遍歷文件夾 a 下的所有文件時(shí),經(jīng)常先深度遍歷了其中的文件夾,導(dǎo)致文件排在這些文件夾深度遍歷的結(jié)果之后,在生成的 README 中無(wú)法看出其準(zhǔn)確位置。

解決方法還比較簡(jiǎn)單,就是在每一次遞歸的遍歷方法中都建立一個(gè)隊(duì)列,遍歷到文件夾先推入隊(duì)列,遍歷到文件則展示。所有文件遍歷結(jié)束后,將隊(duì)列中的文件夾依次取出并遍歷。這樣既滿足了要求,也沒(méi)有對(duì)深度優(yōu)先遍歷造成影響。

更好的是,JS 的數(shù)組原生支持了push方法,使得我不用再寫(xiě)一個(gè)隊(duì)列的實(shí)現(xiàn)。

結(jié)語(yǔ)

盡管只是一個(gè)微不足道的小工具,我還是很開(kāi)心能夠根據(jù)自己的實(shí)際需求開(kāi)發(fā)了 yuki,更開(kāi)心有機(jī)會(huì)開(kāi)發(fā)一個(gè)能在名字中夾私貨的項(xiàng)目(早在看到 vue 的版本名時(shí)我就一直心心念念了)。

如果你覺(jué)得這個(gè)小工具還不錯(cuò),或者使用時(shí)覺(jué)得很方便、減輕了重復(fù)的工作負(fù)擔(dān),那么不妨為 yuki 點(diǎn)一個(gè) star,因?yàn)槲毅裤街茉诋厴I(yè)前擁有一個(gè)自己的 100+ star 項(xiàng)目。

我覺(jué)得可以

當(dāng)然,我更希望這些 star 是憑借我自己的開(kāi)發(fā)創(chuàng)意和技術(shù)所得到的認(rèn)可的。而我的開(kāi)發(fā)經(jīng)驗(yàn)確實(shí)不太足,所以如果你覺(jué)得這個(gè)工具不太好使、代碼糟糕、發(fā)現(xiàn)了 bug,或是有可以增加的功能,也歡迎你開(kāi) issue 或者提交 PR 來(lái)告知我。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容