我们都用过 vue 的cli ,或者 react的cli,  亦或是其他的cli 如 vite 等。他们都是提供了一个全局命令,然后在终端执行这个全局命令就可以创建出模板项目。今天我们就自己做一个,给自己用的脚手架项目,帮助自己开发一些项目。

现在我们来造点需求。

背景:我们要在nextjs 项目中,添加页面路由,用过nextjs 的同学应该知道,这个pages 下面的文件就是页面路由。我们一般添加页面都在pages文件夹下新建文件 ,有时候还会在pages同级文件夹下新建components 文件夹,来放我们页面的组件。

要求:

    1. 可以单独创建一个页面路由
    2. 如果页面复杂,那我需要在pages同级目录下创建一个components文件夹下创建同名的组件文件夹
    3. 可以控制是否生成style 文件

    分析:我们回忆下@vue/cli 这样的脚手架是如何使用的

npm install -g @vue/cli

vue create my-project

全局安装之后 开始使用这个全局命名。

那么我们就按照这个思路倒着打。

因此我们也需要搞一个全局命令,然后执行我们全局命令后,就可以执行我们想要的动作,创建文件夹,写文件等。

  1. 创建空项目,next-project-add-page
  2. npm init
  3. 修改 package.json, 添加 bin 字段
  4. 本地调试,先生成软连接 来让我们可以使用 next-add-page 命名, npm  link 
  5. 核心代码编写
{
"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的更多相关文章

  1. Node & CLI

    Node & CLI cli 生成文件的原理是什么 https://nodejs.org/api/cli.html http://nodejs.cn/api/cli.html CLI & ...

  2. 新建一个express工程,node app无反应

    1.问题描述 新建一个express工程,node app以后无反应,浏览器输入localhost:3000,显示如下 2.解决方法 在app.js文件中加入如下代码 app.listen(3000, ...

  3. 搭建一个最简单的node服务器

    搭建一个最简单的node服务器 1.创建一个Http服务并监听8888端口 2.使用url模块 获取请求的路由和请求参数 var http = require('http'); var url = r ...

  4. 打算写一个《重学Node.js》系列,希望大家多多支持

    先放上链接吧,项目已经开始2周了:https://github.com/hellozhangran/happy-egg-server 想法 现在是2019年11月24日,还有人要开始学习Node.js ...

  5. 分布式ID生成服务,真的有必要搞一个

    目录 阐述背景 Leaf snowflake 模式介绍 Leaf segment 模式介绍 Leaf 改造支持RPC 阐述背景 不吹嘘,不夸张,项目中用到ID生成的场景确实挺多.比如业务要做幂等的时候 ...

  6. 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 ...

  7. node cli & emoji

    node cli & emoji cli $ yarn add node-emoji $ npm i node-emoji https://github.com/omnidan/node-em ...

  8. 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 ...

  9. linux & node & cli & exit(0) & exit(1)

    linux & node & cli & exit(0) & exit(1) exit(0) & exit(1) demo exit(0) === OK exi ...

  10. 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 ...

随机推荐

  1. maven父子项目,由于pom文件中的<packaging>pom</packaging>导致报数据源配置错误

    啊啊啊~~~ 又是踩坑的一天!!! 我在子模块中进行开发,然后子模块的pom文件中也写了<packaging>pom</packaging>导致报数据源配置错误.具体内容如下图 ...

  2. Docker基本命令之 镜像管理

    镜像管理 docker常用基础命令: 查看docker版本信息:docker version 查看docker系统信息:docker info docker服务相关: 查看docker服务:syste ...

  3. Sky Full of Stars

    题目链接: luogu cf 题目大意: 给定一个 \(n \times n\) 的矩形,在里面填充三种颜色,求使得至少一行或至少一列同色的方案数. 解法 容斥 我们不去考虑反演,直接开始容斥,我们不 ...

  4. modesim : mosel not define

    这个星期仿真sdram时,添加的sdram 模型文件在modesim中总是找不到,在qq群里提问和私聊别人都没有得到解决方法.于是自己摸索了好多天.终于得到了解决. 可以看到modesim里面work ...

  5. 【Leetcode第285场周赛】——周赛总结

    1.6027. 统计数组中峰和谷的数量 - 力扣(LeetCode) (leetcode-cn.com) 给你一个下标从 0 开始的整数数组 nums .如果两侧距 i 最近的不相等邻居的值均小于 n ...

  6. nuxt.js的导航守卫

    一.使用router.js 重构项目时还行使用原来的router.js也是可以的,需要下载插件惊醒配置,这时候vue-cli中怎么用,nuxt中就怎么使用导航守卫,几乎一样 二.使用nuxt.js 1 ...

  7. 【python】第二模块 步骤一 第二课、数据库表的相关操作

    第二课.数据库表的相关操作 一.课程介绍 1.1 课程介绍 学习目标 管理逻辑库和数据表 创建.删除.修改逻辑库和数据表 了解常用的数据类型和约束 字符串.整数.浮点数.精确数字.日期.枚举.主要约束 ...

  8. Spring面试题大汇总

    1.Spring的IOC和AOP机制? 我们在使用spring框架其实就是为了实现IOC,依赖注入,和AOP,面向切面编程,主要有两种设计模式工厂模式和代理模式,IOC就是典型的工厂模式,通过sess ...

  9. Ubuntu系统update时提示源不安全被禁用的一种解决办法

    参考自这篇文章Ubuntu系统update时提示源不安全被禁用 - 知乎 (zhihu.com). 安装好Ubuntu18.04并更换清华源后,在运行 sudo apt update 更新源时报错如下 ...

  10. 杭电OJ刷题指南(ACM)

    杭州电子科技大学Oj是著名的算法竞赛刷题网站!!