前言
开始教程之前,我们先用5W法来了解下本文的基调。
What
CLI是command-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-staged和Eslint,在代码提交前做一些羞羞的事。
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三连!