传统的前端项目初始流程一般是这样:
可以看出,传统的初始化步骤,花费的时间并不少。而且,人工操作的情况下,总有改漏的情况出现。这个缺点有时很致命。
甚至有马大哈,没有更新项目仓库地址,导致提交代码到旧仓库,这就很尴尬了。。。
基于这些情况,编写命令行工具(CLI)的目的就很明确:
用于新项目工程的初始化利用工具进行初始化,可以节省项目初期的准备时间避免出现改漏的情况杜绝未更新项目版本仓库地址的问题
以下是新的流程示意图:
以下是自动化流程图:
从流程图可以得出两个重要的信息:
配置信息模板文件
命令行工具的角色,是负责将两个信息进行融合,提供一个交互平台给用户。
配置信息的获得,需要靠和用户进行交互。由于程序员一般是用终端输入命令进行项目操作。所以,这里选择了两个工具进行支撑。
commander
借鉴Ruby commander理念实现的命令行执行补全解决方案
commander可以接收命令行传入的参数
例子:
npg-cli --help ♫ ♫♬♪♫ npm-package-cli ♫ ♫♬♪♫ Usage: npg-cli [options] Options: -V, --version output the version number -h, --help output usage information run testcli and edit the setting.
inquirer
常用交互式命令行用户界面的集合。
inquirer用询问式的语句,与用户进行交互,接收参数
例子:
npg-cli ♫ ♫♬♪♫ npm-package-cli ♫ ♫♬♪♫ Follow the prompts to complete the project configuration. ? project name test ? version 1.0.0 ? description
前端的JavaScript 模板引擎,比如ejs,jade等。可以根据传入的参数,对模板标签进行替换,最终生成html。
如果把所有项目文件,不管文件后缀名,都看成是ejs模板,则可以在文件内容中使用ejs语法。
再根据配置信息进行替换,最终生成新文件。
其实,业界依据这个想法,已经有成熟的工具产生。
mem-fs
mem-fs是对文件进行读取,存入内存中。
mem-fs-editor
mem-fs-editor是对内存中的文件信息,使用ejs语法进行编译。最后调用commit方法输出最终文件。
提示信息,除了console.log,还可以使用色彩更丰富的chalk。
这样,可以输出更直观、友好的提示。
文件操作,有业界成熟的shelljs。
利用shelljs,可以在项目中简化以下步骤:
一些项目文件,不需要修改,只用直接copy。可以使用shelljs.copySync同步方式生成。一些文件夹,需要提前构建,可以使用shelljs.mkdir进行创建
以下按我做的开源项目——npm-package-cli的创作过程进行分拆、讲解。
新建项目文件夹npm-package-cli,并在该文件夹下运行npm init,生成package.json。
项目结构如下:
npm-package-cli |-- package.json
这里要生成的全局指令是npg-cli。
新建文件夹bin,并在文件夹下新建名称为cli的shell脚本文件(注意:不能有后缀名)。
clishell脚本文件内容如下:
#!/usr/bin/env node console.log('hello world');
其中,#!/usr/bin/env node是告诉编译器,以node的方式,运行代码。
并在package.json加入以下内容:
"bin": { "npg-cli": "bin/cli" }
此时,项目结构如下:
npm-package-cli |-- bin |-- cli |-- package.json
链接指令有两种方式:
npm link
npm install -g
两种方式,都需要在npm-package-cli文件夹下运行,才能生效。
作用是把npg-cli指令,指向全局的bin文件下,实现软链。
在任意文件夹下运行命令:
npg-cli # 输出 hello world
到这里,一个基本的指令就算完成了,接下来是指令的工作内容细化。
Creation的作用是整合所有操作,并提供接口给指令文件cli。
Creation的结构如下:
class Creation{ constructor(){ // code } do(){ // code } // other function }
其中do方法暴露给脚本文件cli调用。
Creation类放在src/index.js中。
此时,项目结构如下:
npm-package-cli |-- bin |-- cli |-- src |-- index.js |-- package.json
#!/usr/bin/env node const Creator = require('../src/index.js'); const project = new Creator(); project.do();
这样,只要实现好do方法,就可以完成npg-cli指令的运行了。
实现npg-cli --help,需要借助上文提到的工具commander。
新建src/command.js文件,文件内容如下:
const commander = require('commander'); const chalk = require('chalk'); const packageJson = require('../package.json'); const log = console.log; function initCommand(){ commander.version(packageJson.version) .on('--help', ()=>{ log(chalk.green(' run testcli and edit the setting.')); }) .parse(process.argv); } module.exports = initCommand;
此时,项目结构如下:
npm-package-cli |-- bin |-- cli |-- src |-- command.js |-- index.js |-- package.json
然后在Creation.do方法内执行initCommand()即可生效。
// src/index.js Creation const initCommand = require('./command'); class Creation{ // other code do(){ initCommand(); } }
此时,运行npg-cli --help指令,就可以看到:
Usage: npg-cli [options] Options: -V, --version output the version number -h, --help output usage information run testcli and edit the setting.
要获取用户输入的信息,需要借助工具inquirer。
新建src/setting.js文件,文件内容如下:
const inquirer = require('inquirer'); const fse = require('fs-extra'); function initSetting(){ let prompt = [ { type: 'input', name: 'projectName', message: 'project name', validate(input){ if(!input){ return 'project name is required.' } if(fse.existsSync(input)){ return 'project name of folder is exist.' } return true; } }, // other prompt ]; return inquirer.prompt(prompt); } module.exports = initSetting;
此时,项目结构如下:
npm-package-cli |-- bin |-- cli |-- src |-- command.js |-- index.js |-- setting.js |-- package.json
然后在Creation.do方法内执行initSetting()即可生效。
// src/index.js Creation const initCommand = require('./command'); const initSetting = require('./setting'); class Creation{ // other code do(){ initCommand(); initSetting().then(setting => { // 用户输入完成后,会得到全部输入信息的json数据 setting }); } }
这里,inquirer.prompt方法装载好要收集的问题后,返回的是Promise对象。收集完成之后,要在then方法内拿到配置信息,以便进行下一步模板替换的操作。
模板文件替换,要用到工具mem-fs和mem-fs-editor。
文件操作,要用到工具shelljs。
新建src/output.js文件,文件内容如下(删除了部分代码,以下只是示例,完整项目看最后分享链接):
const chalk = require('chalk'); const fse = require('fs-extra'); const path = require('path'); const log = console.log; function output(creation){ return new Promise((resolve, reject)=>{ // 拿到配置信息 const setting = creation._setting; const { projectName } = setting; // 获取当前命令行执行环境所在文件夹 const cwd = process.cwd(); // 初始化文件夹path const projectPath = path.join(cwd, projectName); const projectResolve = getProjectResolve(projectPath); // 新建项目文件夹 fse.mkdirSync(projectPath); // copy文件夹 creation.copy('src', projectResolve('src')); // 根据配置信息,替换文件内容 creation.copyTpl('package.json', projectResolve('package.json'), setting); // 将内存中的文件,输出到硬盘上 creation._mfs.commit(() => { resolve(); }); }); } module.exports = output;
output方法的作用:
这里最重要的一步,是调用mem-fs-editor的方法后,要执行mem-fs-editor的commit方法,输出内存中的文件到硬盘上。
在Creation.do方法中,调用output方法即可输出新项目文件。
打开src/index.js文件,文件内容增加如下方法:
// src/index.js Creation const initCommand = require('./command'); const initSetting = require('./setting'); const output = require('./output'); class Creation{ // other code do(){ initCommand(); initSetting().then(setting => { // 用户输入完成后,会得到全部输入信息的json数据 setting this._setting = Object.assign({}, this._setting, setting); // 输出文件 output(this).then(res => { // 项目输出完成 }); }); } }
自动初始化一个项目的流程不外乎以下三点:
命令行工具,是对这三点的有效整合,串连成一个规范的流程。
命令行工具中,使用的第三方工具包,都需要用--save的方式安装。
体现在package.json的表现是dependencies字段:
"dependencies": { "chalk": "^2.4.2", "commander": "^3.0.0", "fs-extra": "^8.1.0", "inquirer": "^6.5.0", "mem-fs": "^1.1.3", "mem-fs-editor": "^6.0.0", "shelljs": "^0.8.3" },
这样,其他用户在安装你发布的CLI工具时,才会自动安装这些依赖。
我创作的npm-package-cli,是专门用于生成个人npm package项目的CLI工具。
生成的项目,囊括以下功能点:
支持各种模块规范(AMD、CMD、CommonJS、ESModule)
CLI工具安装方式:
npm install -g npm-package-cli
开源仓库地址:https://github.com/wall-wxk/npm-package-cli
如果对你有所帮助,麻烦给个Star,你的肯定是我前进的动力~
总结
以上所述是小编给大家介绍的node命令行工具之实现项目工程自动初始化的标准流程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
工欲善其事,必先利其器。学好SQLite的命令行工具,对于我们学习SQLite本身而言是非常非常有帮助的。最基本的一条就是,它让我们学习SQLite的过程更加轻松愉快。言归正传吧,在SQLite的官方下载网站,提供了支持多个平台的命令行工具,使用该工具我们可以完成大多数常用的SQLite操作,就像sqlplus之于Oracle。以下列表给出了该工具的内置命令: 命令名 命令说明 .help 列出所
命令行工具 meteor help 获取 meteor 命令行使用帮助。运行 meteor help 会列出meteor所有命令。运行meteor help <command>会打印出关于meteor <command>的详细帮助。 meteor create <name> 创建一个名为<name>的子目录,并在里面新建一个Meteor应用。 met
web3j的完全jar文件分发包对每一次发布都提供命令行工具。命令行允许你从终端(terminal)使用web3j的一些功能: 这些工具提供: 钱包创建 钱包密码管理 从一个钱包转移到另一个钱包以太币 solidity智能合约封装包的产生 命令行工具可以从github项目存储库的releases页面下载zipfile/tarball包,或者通过源代码自己编译获得;OS X用户也可以通过Homebr
命令行工具 web3j的jar包为每一个版本都提供命令行工具。命令行工具允许你直接通过一些命令使用web3j的一些功能: 钱包创建 钱包密码管理 资金从钱包转移到另一个 solidity编写的智能合同功能打包 请参阅文档以获得命令行相关的进一步的信息。
命令行是程序员的好伙伴 作为一名优秀的程序员,熟练的命令行操作也是必不可少的。在『Laravel 实战教程』系列课程中,我们的很多操作都会使用到命令行,如: Git 操作; 虚拟机管理; 部署到线上等。 工欲善其事、必先利其器,命令行工具的选择也尤其重要。这里为了课程讲解的一致性,也为了避免读者在学习中犯不必要的错误,我们为各个平台挑选了专属的命令行工具,请大家配合使用。 Mac 用户 Mac O
imi 的命令行工具使用注解来定义 注解 @Tool Imi\Tool\Annotation\Tool,写在类上,用于定义工具名称 属性名称 说明 name 工具名称 @Operation Imi\Tool\Annotation\Operation,写在方法上,用于定义工具动作名称 属性名称 说明 name 工具动作名称 co 是否自动开启协程,默认为true @Arg Imi\Tool\Anno