手摸手教学之-用node实现一个CLI工具

936 阅读5分钟

前言

开始教程之前,我们先用5W法来了解下本文的基调。

What

CLIcommand-line interface的缩写,用码农圈的黑话来说就是命令行界面。它有个好基友叫GUIGraphical User Interface-图形用户界面。两者区别自行脑补。

Why

先来灵魂三问:既然有方便直观的GUI,我们为什么要开发CLI呢;大部分能想到的功能需求,已经有了开源的CLI工具,为什么还要自己造轮子呢;明明想不出第三问,为什么非要凑个灵魂三问呢? 为了装B,为了装B,为了装B.

Who,When,Where

接下来就由我带领大家在此小小的装个X.

PS:鉴于文章篇幅较长,大家可以先看源码,结合源码的git log看文章。

项目依赖

我们先概览一下本教程中我们需要用的依赖库。

Babel:本教程使用最新JS语法,需要用Babel将代码转换为向后兼容的JS语法。

Commitizen: 用来规范我们的commit message。

Husky: Git hooks工具,配合Lint-stagedEslint,在代码提交前做一些羞羞的事。

Lint-staged: 过滤出Git代码暂存区文件(被git add的文件)的工具。

Eslint: 代码检查工具,现在也干代码格式化的勾当。

初始化项目

什么也别说,先打开你的 Github 创建一个新的项目 skeleton-project-generator

在这里复杂的啰嗦很多句,不想看的可以跳过本段,不影响开发。(一开始确实写了很多,但最后回过头来审文的时候发现又臭又长,就删了)大概意思就是,做的项目多了,每个项目都有相同的部分,每次都是通过复制一些通用的最佳实践部分创建项目,觉得很烦,于是就想维护一个项目模板项目,而通过项目模板创建项目也会有一些重复的操作,于是就又写了这个CLI工具来偷懒,不知道我说清楚了没...

打开一个你中意的命令行终端(推荐一下骚气逼人的Cmder),git clone下我们创建好的项目。

项目克隆到本地后,用你的代码编辑工具(推荐使用Vscode,我下面的一些操作都以Vscode为基础)打开它。

配置EditorConfig

为了在多人协作时,保证项目在不同的编辑器或IDE中保持一致的编码样式,我们使用EditorConfig来进行约束。 首先我们先给Vscode装上EditorConfig for VS Code这个插件并启用,然后在项目根目录下添加一个新的文件:.editorconfig

# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab

我们先尝试进行一次对项目修改的git提交,你可以选择使用Sourcetree这样的GUI工具,也可以使用Git自带的CLI工具。具体命令我就不写了,不然就跑题跑得太远了。

npm init

我们使用npm init命令来初始化一个Nodejs项目。

$skeleton-project-generator(main -> origin): npm init

按照命令行提示,输入相应的值就OK了。

git提交一下。这里给个建议,尽量让我们的git提交细粒化一些,不要修改了一大推东西后,一次性提交,尽量一次提交就是做一件事或一类事,这样对于你后期寻找bug,和做一些其他骚操作都会有很大帮助。

配置Commitizen

在此之前,我们已经进行过两次git提交,但是你会发现我们的Commit Message很随意,一旦我们的git提交越来越多的时候,就会发现,又给自己挖坑了。一份清晰、简洁、规范的Commit Message对以后我们进行代码审查、信息查找、版本回退等操作时有很大帮助。

Commitizen就是一款用来规范我们git提交的工具。(具体详情请查看文档,我们下面直接用起来)

先安装相关依赖:

$skeleton-project-generator: npm install --save-dev commitizen
$skeleton-project-generator: npx commitizen init cz-conventional-changelog --save-dev --save-exact

执行完命令后,Commitizen会在我们的package.json文件里自动生成配置信息:

 "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }

我们在package.json中新增一个脚本指令:

  "scripts": {
    "commit": "cz"
  },

通过git add指令或在Sourcetree中将我们项目中刚刚所有的变更添加到暂存区,然后执行命令:

 $skeleton-project-generator:npm run commit

然后按照提示,输入相应的值就OK了。

配置npmrc(可忽略)

不知道你有没有发现,经过我们刚刚的一番骚操作,项目中多了一个package-lock.json文件,它的具体好处我是没体会到过,恶心得地方倒是经常遇到,本节的目的就是干掉它,干掉它,干掉它。如果你爱它,可以忽略本节,影响不大。

要想干掉它,就在根目录下创建一个新的文件.npmrc:

package-lock=false

然后删掉package-lock.josn这个文件就OK了。

提交吧,骚年!(git 三连,git add,npm run commit,git push

配置Babel

本项目我们将采用最新的JS语法,而这些语法可能nodejs还不支持,于是我们就需要使用到Babel,作为一个工具链,Babel可以将我们使用最新JS语法编写的代码转换为向后兼容的JS语法,以便能够运行在当前和旧版本的node环境中(或其他环境)。 话不多说,上才艺:

$skeleton-project-generator:$ npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-transform-async-to-generator @babel/plugin-syntax-dynamic-import

在根目录添加 babel.config.json (需要Babel v7.8.0或更高版本)文件:

{
    "presets": [
        "@babel/preset-env"
    ],
    "plugins": [
        "@babel/plugin-transform-runtime",
        "@babel/plugin-transform-async-to-generator",
        "@babel/plugin-syntax-dynamic-import"
    ]
}

我们在package.json中新增一个脚本指令:

  "scripts": {
    "build": "babel src -d dist"
  },

运行此命令,会将src目录下的所有代码编译到dist目录,src目录是我们的源码目录,我们接下来创建,dist目录及其中所有的文件都是我们执行命令后,由Babel自动生成。

我们在根目录下创建src目录,并创建一个index.js文件:

import Os from 'os';
console.log(Os.cpus);

如果我们直接执行我们的代码,看看会出现什么问题:

$skeleton-project-generator:node ./src/index.js

控制台会报一个语法错误:SyntaxError: Cannot use import statement outside a module

说明我们当前的node环境不支持import语法,it's Babel show time!

$skeleton-project-generator:npm run build & node ./dist/index.js

上面的指令是先执行npm run build,执行成功后再执行node ./dist/index.js命令的意思。

Well done!我们能看到控制台打印出了cpu信息,说明我们干的事儿成了!

git 三连!

配置Eslint

当我们深入代码逻辑开发的时候,我们的代码可能或多或少会出现一些低级错误,而Eslint就是为了帮助我们在开发的时候纠正这些低级错误。

Eslint是一个用来识别ECMAScript 并且按照规则给出报告的代码检测工具,使用它可以避免低级错误和统一代码的风格。

先安装依赖:

$skeleton-project-generator:npm i --save-dev eslint eslint-config-airbnb-base eslint-plugin-import

根目录下添加 .eslintrc 文件:

{
  "extends": "airbnb-base"
}

安装Vscode插件ESLint并启用。

我们再回到我们之前创建的src/index.js文件,有错误提示了,意不意外,惊不惊喜!

我们可以安装提示一个个修改,也可以通过刚刚安装的插件自带的一键修复来修复。

git三连!