1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        使用 Node,如何制作一個(gè)專業(yè)的命令行工具?

        共 6010字,需瀏覽 13分鐘

         ·

        2021-11-16 19:14

        使用 Node 開發(fā)一個(gè)命令行工具很有意思,較為其它語言而言也更加簡單,今天山月寫一篇文章總結(jié)一下如何寫一個(gè)友好且健壯的 cli 工具。

        在閱讀完本篇文章之后,「強(qiáng)烈推薦閱讀」 Github 上的一篇文章: Node CLI 工具最佳實(shí)踐。正如它的標(biāo)題而言,在 Github 上用于 2000 顆星星的該文章的確稱得上最佳實(shí)踐。

        長按識(shí)別二維碼查看原文

        標(biāo)題:Node CLI 工具最佳實(shí)踐 ? ? ?

        「目錄」

        • 1. 命令行工具與環(huán)境變量 PATH

        • 2. 原理

        • 3. 從 package.json 說起

        • 4. 一個(gè)執(zhí)行環(huán)境

        • 5. 解析命令輸入

        • 6. 用戶體驗(yàn)與豐富的色彩

        • 7. 可交互性

        • 8. 發(fā)布與安裝

        • 9. 總結(jié)

        1. 命令行工具與環(huán)境變量 PATH

        什么是命令行工具?

        最初印象大致是 ls,pwd 這些能夠「在終端執(zhí)行的系統(tǒng)命令」,這樣的命令很多,數(shù)不勝數(shù),被稱為系統(tǒng)內(nèi)置命令。

        如果使用 which 查看他們的來歷,則能夠發(fā)現(xiàn)他們的廬山真面目:

        # 由此可知,pwd 為一個(gè)系統(tǒng)內(nèi)置命令
        $ which pwd
        pwd: shell built-in command

        隨著對(duì) Linux/Unix 系統(tǒng)理解及使用的逐漸加深,發(fā)現(xiàn)了諸多的非內(nèi)置命令:

        • top

        • ps

        • netstat

        • dig

        • man

        使用 which 追根究底,發(fā)現(xiàn)它們實(shí)際執(zhí)行的路徑在某一個(gè) bin 目錄

        $ which top
        /usr/bin/top

        $ which ps
        /bin/ps

        而這些 bin 目錄在環(huán)境變量 PATH 中,豁然開朗。簡而言之: 「在環(huán)境變量的 PATH 中路徑的命令可在其它任意地方執(zhí)行」。

        export PATH=$HOME/bin:/usr/local/bin:$PATH

        說起環(huán)境變量,你可以使用 env 列出所有的環(huán)境變量。

        $ env
        LANG=zh_CN.UTF-8
        USER=root
        LOGNAME=root
        HOME=/root
        PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

        你好像想起點(diǎn)什么?在大學(xué)配置 Java 時(shí)被環(huán)境變量支配的各種恐懼?

        是了,所有語言的可執(zhí)行命令都要放在 PATH 下,只不過其它語言的安裝工具自動(dòng)給你做了這件事,而 Java 讓你自己來處理它。

        • java

        • python

        • pip

        • node

        • npm

        「開發(fā)命令行的原理也是如此,將你開發(fā)的命令行工具腳本置于環(huán)境變量 PATH 下的路徑之中」,而本篇文章的目標(biāo)就是:

        使用 Javascript 這門前端開發(fā)者熟悉的語言,借助 Node 環(huán)境,開發(fā)一個(gè)命令行工具。

        2. 原理

        先看兩個(gè) Node 的命令行工具:

        • [serve](https://github.com/vercel/serve) 一個(gè)流行的靜態(tài)文件服務(wù)器,大名鼎鼎 Vercel 團(tuán)隊(duì)(Next.js 團(tuán)隊(duì))的力作

        • markdown 一個(gè)山月自己寫的解析 URL 到 markdow 的命令行。通過命令解析出他們指向的符號(hào)鏈接

        $ ls -lah $(which serve)
        lrwxr-xr-x 1 xiange admin 65B 7 12 2020 /usr/local/bin/serve -> ../../../Users/shanyue/.config/yarn/global/node_modules/.bin/serve

        $ ls -lah $(which markdown)
        lrwxr-xr-x 1 xiange admin 48B 1 28 20:06 /usr/local/bin/markdown -> ../lib/node_modules/markdown-read/md-read-cli.js

        從中可以看出關(guān)于 Node 全局命令行的原理:

        1. npm 全局下載某個(gè) package 到路徑 /usr/local/lib/node_modules 下 (yarn 同理,對(duì)應(yīng)路徑 ~/.config/yarn/global/node_modules)

        2. 根據(jù)該庫的 package.json 中 bin 字段的指示,把對(duì)應(yīng)的命令行路徑通過符號(hào)索引掛載到 PATH 路徑

        3. 對(duì)應(yīng)的二進(jìn)制腳本添加 x 權(quán)限 (可執(zhí)行文件權(quán)限)

        簡而言之,Node 環(huán)境下的命令行工具,借助的原理無非是「環(huán)境變量 Path」與一個(gè)「符號(hào)鏈接」

        3. 從 package.json 說起

        「package.json 中的 bin 字段」,用以指定最終的命令行工具的名字

        {
        "bin": {
        "serve": "./bin/serve.js"
        }
        }

        如上所示,server 是最終在終端執(zhí)行的命令,而 ./bin/serve.js 是該命令實(shí)際執(zhí)行的腳本文件。

        對(duì)于最終可執(zhí)行的命令行工具,Node 項(xiàng)目一般傾向置文件于 bin 目錄下,如以下 Typescript 關(guān)于它命令行的配置:

        {
        "bin": {
        "tsc": "./bin/tsc",
        "tsserver": "./bin/tsserver"
        },
        }

        4. 一個(gè)執(zhí)行環(huán)境

        對(duì)于可直接執(zhí)行的文件,需要指明執(zhí)行環(huán)境,首行添加一行說明:

        #!/usr/bin/env node

        // code 往下寫

        這一句話是啥子意思了?

        1. #! 加解釋器,標(biāo)明該文件使用 /usr/bin/env node 來執(zhí)行

        2. /usr/bin/env 為 env 的絕對(duì)路徑,用以在 PATH 路徑中執(zhí)行命令 (在各種不同的系統(tǒng)中,node 命令行的位置不同,因此使用 env node 找到路徑并執(zhí)行)

        3. env node 在人為層面可理解為執(zhí)行 node 命令

        所以這句話的意思是: 「使用 node 解釋器來執(zhí)行這個(gè)腳本,而通過 env node 能夠正確定位到 node 解釋器的位置」

        // 如果不寫 #!/usr/bin/env node,需要這么執(zhí)行
        $ node serve .

        // 如果寫上 #!/usr/bin/env node,可以直接執(zhí)行
        $ serve .

        5. 解析命令輸入

        在服務(wù)端應(yīng)用中,可以通過 request.url.querystringrequest.body 獲取用戶輸入。

        而在命令行工具中,可通過 progress.argv 可獲取用戶輸入。請(qǐng)看以下示例:

        $ node cmd.js 1 2 3
        // Output: [
        // '/usr/local/bin/node',
        // '/Users/shanyue/cmd.js',
        // '1',
        // '2',
        // '3',
        // ]
        process.argv

        根據(jù)解析 process.argv 可以定制格式來獲取各式各樣的參數(shù)作為命令行的輸入。`

        當(dāng)然解析參數(shù)也要參照 POSIX 兼容的基本規(guī)律: 格式、可選、必選、簡寫、說明、幫助等等。命令行工具命名協(xié)議 文章中已說的足夠詳細(xì)。

        長按識(shí)別二維碼查看原文

        標(biāo)題:命令行工具命名協(xié)議 ? ? ?
        // 一個(gè)較為規(guī)整的命令行幫助
        $ node --help
        Usage: node [options] [ script.js ] [arguments]
        node inspect [options] [ script.js | host:port ] [arguments]

        Options:
        - script read from stdin (default if no file name is provided,
        interactive mode if a tty)
        -- indicate the end of node options
        --abort-on-uncaught-exception aborting instead of exiting causes a core file to be generated for
        analysis
        -c, --check syntax check script without executing
        --completion-bash print source-able bash completion script
        --cpu-prof Start the V8 CPU profiler on start up, and write the CPU profile to
        disk before exit. If --cpu-prof-dir is not specified, write the profile
        to the current working directory.

        因?yàn)?POSIX 兼容繁雜的規(guī)則,以此衍生出了關(guān)于解析命令參數(shù)的多個(gè)庫,站在巨人的肩膀上,在實(shí)際工作中就直接開用吧!

        • yargs: Star 8.5K,周下載量 4900K

          長按識(shí)別二維碼查看原文

          標(biāo)題:yargs ? ? ?
        • commander: Star 19.7K,周下載量 5300K,tj 大神的作品

          長按識(shí)別二維碼查看原文

          標(biāo)題:commander ? ? ?

        以下是一個(gè) Demo: 使用 commander 解析不同的輸入指令

        const { program } = require('commander')

        // 解析不同的指令輸入
        program
        .option('-d, --debug', 'output extra debugging')
        .option('-s, --small', 'small pizza size')
        .option('-p, --pizza-type ', 'flavour of pizza')

        program.parse(process.argv)

        const options = program.opts()
        console.log(options)

        6. 用戶體驗(yàn)與豐富的色彩

        77c09361386912f8b48df65838fc23e6.webpNext 構(gòu)建輸出

        以上是 next build 命令行的標(biāo)準(zhǔn)輸出,擁有色彩多樣的高亮格式與豐富的列表展示,可以提供更豐富的用戶體驗(yàn)。

        目前大部分終端已支持彩色輸出,即通過 ANSI 編碼進(jìn)行控制,并擁有成熟的庫控制色彩。如 ansi-styles

        長按識(shí)別二維碼查看原文

        標(biāo)題:ansi-styles ? ? ?
        import styles from 'ansi-styles';

        console.log(`${styles.green.open}Hello world!${styles.green.close}`);

        豐富的高亮色彩如同代碼高亮一樣使用戶可以快速抓住重點(diǎn)。把異常、警告、成功的信息用不同的顏色標(biāo)出,命令行工具的輸出一目了然。在現(xiàn)代構(gòu)建工具,如 Webpack 下,也大都支持彩色輸出。

        以下是在命令行工具中常用的兩個(gè)較為高級(jí)的色彩庫,支持多種多樣色彩的輸出,當(dāng)然基本原理仍是 ANSI 編碼。

        • chalk

          長按識(shí)別二維碼查看原文

          標(biāo)題:chalk ? ? ?
        • colors

          長按識(shí)別二維碼查看原文

          標(biāo)題:colors ? ? ?

        以下是 chalk 示例,ErrorWarning 信息用不同的顏色表示

        const chalk = require('chalk')

        const error = chalk.bold.red
        const warning = chalk.keyword('orange')

        console.log(error('Error!'))
        console.log(warning('Warning!'))

        7. 可交互性

        在 Web 中,可使用 Input 來展現(xiàn)豐富多彩的表單,如開關(guān)、多選、單選、輸入框等。

        而在命令行工具中,也可借用多種庫來實(shí)現(xiàn)強(qiáng)交互性。

        • enquirer

          長按識(shí)別二維碼查看原文

          標(biāo)題:enquirer ? ? ?
        • ora

          長按識(shí)別二維碼查看原文

          標(biāo)題:ora ? ? ?
        • ink

          長按識(shí)別二維碼查看原文

          標(biāo)題:ink ? ? ?

        8. 發(fā)布與安裝

        在辛苦努力寫完一個(gè) cli 工具后,就是檢驗(yàn)成果的時(shí)候。發(fā)布到 npm 倉庫,可使所有人使用你的命令行工具,這也是最重要的一步

        # 發(fā)布之前需要 npm login,登錄到 npm registory
        $ npm publish

        發(fā)版成功后全局下載命令行工具,開始使用,示例用它抓取下我的博客首頁

        $ npm i -g markdown-read
        /usr/local/bin/markdown -> /usr/local/lib/node_modules/markdown-read/md-read-cli.js
        + [email protected]
        added 102 packages from 72 contributors and updated 10 packages in 33.15s

        $ markdown https://shanyue.tech
        ## [#](#山月的瑣碎博客記錄) 山月的瑣碎博客記錄

        本博客關(guān)于平常工作中在前端,后端以及運(yùn)維中遇到問題的一些文章總結(jié)。以后也會(huì)做系列文章進(jìn)行輸出,如前端高級(jí)進(jìn)階系列,個(gè)人服務(wù)器指南系列。個(gè)人微信 shanyue94,歡迎添加交流

        ## [#](#名字由來) 名字由來

        9. 總結(jié)

        本篇文章由淺至深講解了以下幾方面的內(nèi)容:

        1. 一個(gè)全局可執(zhí)行的命令行工具的原理是什么

        2. 在 Node 中開發(fā)一個(gè)命令行工具所需要的配置

        3. 開發(fā)命令行工具時(shí)如何解析參數(shù)

        并根據(jù)實(shí)踐,開發(fā)了一個(gè)從 URL 中讀取 Markdown 的小工具: markdown-read,歡迎 Star、下載及使用。

        長按識(shí)別二維碼查看原文

        標(biāo)題:markdown-read ? ? ?

        另外,我基于此命令行做了一個(gè) Web 版,歡迎來體驗(yàn): https://devtool.tech/html-md

        348f08595611e9dd099fced2f2ff54ce.webpHTML To Markdown 網(wǎng)頁版


        瀏覽 56
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            h片免费网站 | 一级黄色录像视频 | 天天日天天干天天日 | 日本WWW在线视频 | 久久久久久久久久成人永久免费视频 | 久热色| 免费无码成人一夜视频 | 小骚逼超碰 | 日韩一区二区无码视频 | 久久朝二 |