搞一个自己用的node-cli
我们都用过 vue 的cli ,或者 react的cli, 亦或是其他的cli 如 vite 等。他们都是提供了一个全局命令,然后在终端执行这个全局命令就可以创建出模板项目。今天我们就自己做一个,给自己用的脚手架项目,帮助自己开发一些项目。
现在我们来造点需求。
背景:我们要在nextjs 项目中,添加页面路由,用过nextjs 的同学应该知道,这个pages 下面的文件就是页面路由。我们一般添加页面都在pages文件夹下新建文件 ,有时候还会在pages同级文件夹下新建components 文件夹,来放我们页面的组件。
要求:
- 可以单独创建一个页面路由
- 如果页面复杂,那我需要在pages同级目录下创建一个components文件夹下创建同名的组件文件夹
- 可以控制是否生成style 文件
分析:我们回忆下@vue/cli 这样的脚手架是如何使用的
npm install -g @vue/cli
vue create my-project
全局安装之后 开始使用这个全局命名。
那么我们就按照这个思路倒着打。
因此我们也需要搞一个全局命令,然后执行我们全局命令后,就可以执行我们想要的动作,创建文件夹,写文件等。
- 创建空项目,next-project-add-page
- npm init
- 修改 package.json, 添加 bin 字段
- 本地调试,先生成软连接 来让我们可以使用 next-add-page 命名, npm link
- 核心代码编写
{
"name": "next-project-add-page",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"next-add-page": "index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"commander": "^10.0.0"
}
}
先上一个能走完大概流程的核心代码,里面一些细节的代码逻辑,我们后面再补充。
// index.js
// console.log(process.argv)
// [
// 'C:\\Program Files\\nodejs\\node.exe',
// 'C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\next-project-add-page\\index.js',
// 'add', // 想要执行的命令
// 'list', // 新增的页面
// '-components', // 是否添加到pages同级的components 文件夹下为 组件
// '-style', // 是否添加样式文件
// ]
const { program } = require('commander');
const child_process = require('child_process');
const { clearInterval } = require('timers');
const fs = require('fs');
const path = require('path');
program
.option('-components')
.option('-style');
program.parse();
console.log(program.opts()) // { Components: true, Style: true }
;
function intervalProgress() {
const readline = require('readline');
const unloadChar='-';
const loadedChar='=';
let i = 0;
let time = setInterval(()=>{
if(i>10){
clearInterval(time);
console.log(`创建完成,请查收`);
process.exit(0);
}
readline.cursorTo(process.stdout,0,1);
readline.clearScreenDown(process.stdout);
renderProgress('文件创建中',i);
i++;
},200);
function renderProgress(text,step){
const PERCENT = Math.round(step*10);
const COUNT = 2;
const unloadStr = new Array(COUNT*(10-step)).fill(unloadChar).join('');
const loadedStr = new Array(COUNT*(step)).fill(loadedChar).join('');
process.stdout.write(`${text}:【${loadedStr}${unloadStr}|${PERCENT}%】`);
}
}
function main(){
if(process.argv[2] && process.argv[2] == 'add') {
if(process.argv[3]) {
// 页面名称
// 判断pages 文件夹是否存在
if(fs.existsSync(`./pages`) && !fs.existsSync(`./pages/${process.argv[3]}`)) {
let subProcess= child_process.exec("cd ./pages && mkdir " + process.argv[3], function(err,stdout){
if(err)console.log(err);
// 读取 tempalte/index.tsx 的文件
let tempalteStr = fs.readFileSync( path.resolve(__dirname, './template/index.tsx'));
fs.writeFile(`./pages/${process.argv[3]}/index.tsx`, tempalteStr, (err) =>{
console.log(err);
});
// 创建style less
if(program.opts().Style && process.argv[3]) {
fs.writeFile(`./pages/${process.argv[3]}/index.less`,'', (err) =>{
console.log(err);
});
}
subProcess.kill();
});
}
}
}
if(program.opts().Components && process.argv[3]) {
// 添加component组件
// 页面名称
// 判断components 文件夹是否存在
if(!fs.existsSync(`./components`)) {
fs.mkdirSync('./components');
}
if(!fs.existsSync(`./components/${process.argv[3]}`)){
let subProcess=child_process.exec("cd ./components && mkdir " + process.argv[3], function(err,stdout){
if(err)console.log(err);
subProcess.kill();
});
}
}
// 展示进度条
intervalProgress();
// 精确点: 实时查询新建的几个文件(文件夹)是否创建成功,如果创建完毕,应该提前结束进度条
}
main();
代码大概解说:
- 使用nodejs 的fs 模块 api,对文件的读写以及文件存在的判断。
- commander 对命令行的解析,得到命令行具体的值后 继续做文件的读写
- 使用 child_process 子进程 对文件的读写
- process.stdout.write 来写终端的输出内容
- 用template 文件夹 放 具体的模板文件,具体生成文件的时候,可以将模板的内容给到相应的文件中

现在可以nextjs 项目下 执行命令:next-add-page add list -components -style
next-add-page:是全局的一个命令
add: 是添加页面的 一个命令
list: 是添加页面的名称
-components: 在 components 文件夹下创建同名的组件 (可选)
-style: 创建样式文件 (可选)
是否可选,取决与代码对这个命令行参数的解析以及操作。
现在执行这个命令行

就可以看到项目中 生成了对应的文件。

到这里基本的需求已经完成了。
接下里是发布,
具体发布到npm 的步骤就不多说了,没有发布过的可以参考下这里,https://cnodejs.org/topic/5823c4411120be9438b02a31
好了,到这里应该知道怎木去开发自己的一个cli 脚手架了。
参考
https://juejin.cn/post/6844903702453551111
https://juejin.cn/post/6857842033084760071
https://www.runoob.com/nodejs/nodejs-fs.html
搞一个自己用的node-cli的更多相关文章
- Node & CLI
Node & CLI cli 生成文件的原理是什么 https://nodejs.org/api/cli.html http://nodejs.cn/api/cli.html CLI & ...
- 新建一个express工程,node app无反应
1.问题描述 新建一个express工程,node app以后无反应,浏览器输入localhost:3000,显示如下 2.解决方法 在app.js文件中加入如下代码 app.listen(3000, ...
- 搭建一个最简单的node服务器
搭建一个最简单的node服务器 1.创建一个Http服务并监听8888端口 2.使用url模块 获取请求的路由和请求参数 var http = require('http'); var url = r ...
- 打算写一个《重学Node.js》系列,希望大家多多支持
先放上链接吧,项目已经开始2周了:https://github.com/hellozhangran/happy-egg-server 想法 现在是2019年11月24日,还有人要开始学习Node.js ...
- 分布式ID生成服务,真的有必要搞一个
目录 阐述背景 Leaf snowflake 模式介绍 Leaf segment 模式介绍 Leaf 改造支持RPC 阐述背景 不吹嘘,不夸张,项目中用到ID生成的场景确实挺多.比如业务要做幂等的时候 ...
- how to read the system information by using the node cli tool?
how to read the system information by using the node cli tool? node cli & get system info demos ...
- node cli & emoji
node cli & emoji cli $ yarn add node-emoji $ npm i node-emoji https://github.com/omnidan/node-em ...
- write a node cli tools, step by step
write a node cli tools, step by step how to write a node cli tools node cli tools, step by step, nod ...
- linux & node & cli & exit(0) & exit(1)
linux & node & cli & exit(0) & exit(1) exit(0) & exit(1) demo exit(0) === OK exi ...
- how to write a node cli tool
how to write a node cli tool https://www.google.com/search?q=how+to+node+cli+tool&oq=how+to+node ...
随机推荐
- python + appium 常用公共方法封装
appium 程序下载安装见之前的帖子:https://www.cnblogs.com/gancuimian/p/16536322.html appium 环境搭建见之前的帖子:https://www ...
- limit资源限制ulimit 详解
系统性能一直是一个受关注的话题,如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件下保证程序的运作,ulimit 是我们在处理这些问题时,经常使用的一种简单手段.ulimit 是一种 L ...
- matlab读写文件
dsp,fpga这些产生的文件大部分都是二进制存储的,知道格式后可以直接读取. 读取后的"可懂"数据如何以"可懂"的形式保存在.dat,.txt,.csv之类文 ...
- kafka例子
<dependencies> <dependency> <groupId>org.apache.kafka</groupId> <artifact ...
- JAVA框架入门理解
一:关于java开发的框架我们可以先从java web开发框架的变迁来给大家简单叙述一下: 1 SSH --Struts+Spring+Hibernate 2 Spring +SpringMVC + ...
- C# core 最简单的方式写入日志
System.IO.StreamWriter sw = System.IO.File.AppendText( LogPath + LogFielPrefix + "Error-" ...
- Android studio Internet跳转活动
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=" ...
- puts()与scanf(“%s”)
使用gets()即使字符串中含有空格,依然可以接收,而scanf()不会. Example: /* 输入一个字符串到字符数组s1中,将s1中的字符串复制到字符数组s2中并输出s2中的字符串. 不用st ...
- [CQOI2014]通配符匹配 题解
第一眼:什么鬼东西ヾ(。`Д´。) 第二眼:显然,这道题要分段处理 类似[TJOI2018]碱基序列\ (建议做一做也是Hash+DP)\ 那你怎么第一眼没看出来 Hash处理+DP==AC 直接上代 ...
- jsp第10个作业
package Servlet; import JDBC.JDBC; import javax.servlet.ServletException; import javax.servlet.annot ...