文章源于 lambdas.dev

每当我们想要创建一个基于 NodeJS 的命令行工具时,就会衍生出一堆问题需要解决,比如如何准备开发环境,如何打包转译代码,如何使代码在转译后保持可调用的状态同时尽可能的压缩体积, 以及怎样设计项目分配 CommandOption 等等,这会浪费巨大的时间,而且并非一定有成果。这时你可以注意到社区几乎所有的命令行工具都是自成一派, 并没有严谨的框架或约定约束,也无所谓的最佳实践,这使想要特别是第一次想要开发命令行工具的开发者望而却步,或是几番努力最后却不尽如人意。

举个例子来说,腾讯的 omi 是一个有众多使用者的框架,但其命令行工具 omi / omi-cli 却让人贻笑大方。仅一些简单的下载和创建模板的任务,造出长篇大论的文件不说,下载 时依赖数千,包的体积巨大,整体项目毫无设计几乎是随心所欲、天马行空,这就是开发者本身并不擅长此道,只学会了 糊屎。(何谓 糊屎,参阅 JS 优雅指南 2)

func 的出现就是为了解决这些问题。func 本身的实现参阅了社区内诸多基于 NodeJS 的命令行工具的优秀实现,与流行的框架设计思路相结合,以优雅的设计、小体积、高性能 等为目标, 同时关注开发者体验,大幅度的提升了命令行工具项目的可扩展性与可读性,几乎是如今 NodeJS 社区中开发命令行工具的最优解。我们可以尝试使用 func 构建一个命令行工具。

构建项目

在以前流行的一些命令行参数解析的库中,我们在构建项目前需要准备大量的脚本与配置,甚至还要解决文件权限、bin、代码转译等等问题,但使用 func,我们可以仅通过一行命令 初始化项目:

npm init func
复制代码

项目初始化后进入文件夹,随机使用 npm installyarn 安装依赖,现在就可以正式开发了。 可以注意到,func 的项目模板中为我们准备了 startbuild 2 个脚本,它们都是由 func-service 驱动的,帮助你一键切换开发与生产模式,我们所要做的就是专注于 命令行逻辑本身,实现逻辑就够了。

实现逻辑

我们可以随意的创建一个类,当它被加上 Command 注解时这就是一个命令,而被加上 Option 注解时就会转变为一个选项:

import { Command } from 'func'@Command({ name: 'test' })
export class Test {
}
复制代码

在命令行中运行 <YOUR NAME> test 时,Test 类将会被调用。选项也是同理。你可以在 constructor 中开始自己的代码,这和你在任何地方写 NodeJS 没有什么 不同,当你觉得差不多的时候,运行 npm build 就可以将它打包,一切就是这么简单。

有时候,当我们需要使用到命令行携带的参数时,比如处理 <NAME> something params -option 这样复杂的输入,你可以直接在类中注入命令行参数,对,就是像 IoC 那样:

@Command({ name: 'test' })
export class Test {constructor(private args: CommandArgsProvider,) {}
}
复制代码

CommandArgsProvider 实际上是一个 class 类型,当你标记一个参数为此类型时,func 会在运行时为你注入所有的命令参数, 同样的也支持 OptionArgsProviderRegisterProvider 等等,你可以在 官方的文档 阅读它们的具体类型。

打包与发布

运行 npm build 可以得到一个打包后的文件,这是由 ncc 编译后的文件,通常它只有一个 (如果携带 extra 可能会有多个,但它们会自动链接), 同时为你链接好了 bin,你要做的唯一一件事就是将包发布出去。为什么 func 使用这种方式发布呢?

我们知道当你在安装一个包或是使用 npx 执行包时 (这在使用命令行工具的人群中很常见),NPM 所花费的时间大约在 3 个部分,即对比包的依赖,下载包,执行。 首先我们知道 func 的项目足够的小,能够大量介绍下载时间,同时也有足够好的性能,现在要解决的就是在大量依赖时的对比分析问题,将文件打包成单文件不依赖 外部环境时会极大的减少所需时间,如果你再将所有的依赖移入 devDependencies 中,几乎能够在一瞬间完成 分析 - 下载 - 运行 这三个步骤。这样的体验是难以想象的。 是的,这里推荐你把所有的依赖当做开发依赖处理,这似乎违背了 NPM Package 的开发哲学,但在使用 func 构建命令行应用时这样做却大有裨益。

在运行 func build 完成的包时,我们注意到几乎无需任何依赖,这是因为在单个文件中已经 bundle 了所有的所需资源,也就意味着用户在运行 .js 文件时, 堆栈中真的就只有 .js 文件内的内容,不会引用其他,不会加载任何无关紧要的东西。此时我们也就无需用户关心 dependencies,甚至可以移除它们,这样一来, 下载或即时运行时就直接跳过了 对比依赖版本 这一步,这其中省略了无数的请求也就会会极大的增加速度,npm init func 能够在 1 秒左右立刻开始安装也是这样的道理。

优化与经验

现在你已经知道了怎样快速的构建一个合格且优雅的命令行工具,那怎样做的更好呢?通常来说你需要遵循这几点:

  • 不因为小功能引入巨大的包,不引入依赖爆炸的包。

    举例来说,download-git-repo 是一个很不错的包,它能够为你节约很多时间,但请注意它依赖了 download,如果你仅为了下载单个文件或只有很少的下载需求时, 这就显得有些大材小用,download 会为你增加约 450 kb 的重量,却只做了一件你 5 分钟可以搞定的事情。同样你的用户也会为此付出巨大的时间代价。

  • 不要显示错误堆栈信息。

    在多数情况下我们都需要尽可能的显示堆栈或是引用的错误信息便于 debug,但是在命令行工具中这样做只会使你的用户非常困惑。这主要归结于命令行中不能很好高亮 的显示代码块,大量的代码信息会使用户不知所措。建议你始终构建一个错误处理模块来解决问题,同时为用户提供良好的反馈,最后可以提供类似于 --debug 的 选项让开发者调试。

  • 不要太依赖同步操作。

    在 NodeJS 与其社区流行的 I/O 库中,我们通常会有异步和同步函数两种选择,如 readFilereadFileSync,虽然同步函数可以为你节约一些开发时间, 但也会阻塞你的代码,很多情况下会有难以理解的问题。比如当你设置定时器显示一个 Loading 图标的同时操作了同步 API,那么你的 Loading 图标就会因为阻塞 而无法运动 (因为无法 render 到终端),或是你同时操作多个文件,同步的 API 会使你花费巨大的时间。

  • 不要发布无用信息。

    命令行工具很多时候的角色是充当复杂的脚本,性能和体验是至关重要的,发布无用的信息在你的 package 中会使下载时间更长。(使用 files 来约束发布的文件)

  • 不要修改临时文件夹与配置区以外的信息。

    对于命令行工具来说,运行时的权限是巨大的,但不要因此弄脏用户的系统。你可以使用 require('os').tmpdir() 获取用户操作系统的临时文件夹目录,无论何时, 你都拥有这里的写权限。

转载于:https://juejin.im/post/5d0652e0f265da1bcb4f2b5d

构建现代化的命令行工具相关推荐

  1. 代码同步工具_构建现代化的命令行工具

    每当我们想要创建一个基于 NodeJS 的命令行工具时,就会衍生出一堆问题需要解决,比如如何准备开发环境,如何打包转译代码,如何使代码在转译后保持可调用的状态同时尽可能的压缩体积, 以及怎样设计项目分 ...

  2. 使用node.js构建命令行工具

    工具说明 inquirer.js:一个封装了常用命令行交互的node.js模块,通过该模块可以很方便地构建一个新的命令行应用. shell.js:跨平台的unix shell命令模块. Node版本: ...

  3. 【Android 命令行工具】Android 命令行工具简介 ( 官方文档 | SDK 命令行工具 | SDK 构建工具 | SDK 平台工具 | 模拟器工具 | Jetifier 工具 )

    文章目录 一.官方文档 二.Android 命令行工具简介 1.SDK 命令行工具 2.SDK 构建工具 3.SDK 平台工具 4.模拟器工具 5.Jetifier 工具 一.官方文档 Android ...

  4. 使用 Cobra 构建命令行工具

    文章首发于个人公众号:阿拉平平 最近折腾了下命令行库 Cobra,和大家分享下.本文演示环境为 CentOS 7.5,Golang 1.11. 文章目录 1. Cobra 介绍 1.1 概念 1.2 ...

  5. golang实现一个linux命令ls命令(命令行工具构建)

    希望2023可以听到这些话: 恭喜你得到了这份工作 恭喜你的建议被采用了 恭喜你被录取了 恭喜你的考试顺利通过了 恭喜你上岸了 恭喜你升职了 恭喜你加薪了 恭喜你体检结果一切正常 在这篇文章下面许个愿 ...

  6. 实用!五款新型 Linux 命令行工具

    使用新的替代工具来改进旧的命令行工具. 作者 | Ricardo Gerardi 译者 | 弯月,责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 以下为译文: 在Linux/Unix系统 ...

  7. 能直接下载了!微软最爽命令行工具登陆Windows 10,GitHub标星已破4万6

    乾明 发自 凹非寺  量子位 报道 | 公众号 QbitAI 微软正式放出命令行工具Windows Terminal. 这个在发布之际就引得开发者大呼"WoW!Awesome!My God! ...

  8. 第三方模块——nodemon是一个命令行工具,用以辅助项目开发、nrm ( npm registry manager ):npm下载地址切换工具

    什么是第三方模块 别人写好的.具有特定功能的.我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又名包. 第三方模块 nodemon nodemon是 ...

  9. Jenkins CLI命令行工具,助你轻松管理 Jenkins

    Jenkins CLI,简称 jcli,一个使用 Golang 开发的开源的 Jenkins 命令行工具.它可以帮忙你轻松地管理 Jenkins.无论你是 Jenkins 插件开发者,还是 Jenki ...

最新文章

  1. setting.xml的mirror、mirrorOf和pom.xml的repositories、repository的关系关联*
  2. 获取运行端口监听的用户身份auth-owner
  3. SVN从win迁移到Linux上
  4. proteus仿真micropython_[MicroPython]TurniBit开发板DIY自动窗帘模拟系统
  5. java array iterator_java数组遍历——iterator和for方法
  6. 三观碎一地:轮子天天见,车轮悖论却2000年无解?
  7. pc wifi 软件 模拟串口_唐山现代新型物联网软件
  8. 简明Python3教程 17.更多
  9. hdu 3951 博弈
  10. 【生信技能树】GEO数据库挖掘 P7 6差异分析
  11. 移动端实现HTML5 mp3录音踩坑指南:系统播放音量变小、一些机型录音断断续续 之 MediaRecorder和AudioWorklet的终极对决
  12. 5.15 vs2019 静态编译_《淫巧系列一》MATLAB编译exe与生成C++库
  13. Multi-Armed Bandits
  14. 26_ue4进阶末日生存游戏开发[僵尸添加动画和扣血效果]
  15. matlab 端点检测 能零比法_基于短时能量与过零率的端点检测的matlab分析
  16. 基于Android的个人记账软件的设计与实现
  17. 大学计算机基础课后题答案中国铁道出版社,大学计算机基础 铁道出版社 2015年第1版 第7章 习题答案...
  18. Docker在Centos7安装、及命令(详细安装教程)
  19. 计算机管理无法启用,无法打开计算机管理怎么办 打开计算机管理的方法
  20. 线性代数-Gilbert Strang(第三部分)

热门文章

  1. 多级页表如何节省内存
  2. JavaScript arguments对象
  3. Git使用笔记(一)
  4. 微软BI 之SSAS 系列 - 在 SQL Server 2012 下查看 SSAS 分析服务的模型以及几个模型的简单介绍...
  5. 对联广告,带关闭,可以移动
  6. Linux防火墙限制指定端口只能由指定IP访问
  7. It is not safe to rely on the system's timezone settings
  8. 嵌入式Web服务器移植
  9. YAML开源库yaml-cpp简介及使用
  10. 在Ubuntu11.10中安装配置OpenCV2.3.1和CodeBlocks