原文地址:https://github.com/screetBloo...
含纯node或者commander实现自己的前端脚手架
文章码字分享不易,希望如果帮到您的话,帮忙github点个star

脚手架

这里主要讲的是如何自定义node命令,拉取项目

snowcat init
// 用户安装我们的命令,就可以一行代码拉取对应项目,可扩展成根据不同命令拉取不同终端模板 

1.脚手架的实现

脚手架作用: 快速搭建一个我们预定义好的模板项目结构
我们这里就做了两件事(已经满足了我目前的需求,可以继续拓展):

  • 1.自定义nodejs命令
  • 2.在nodejs中执行shell命令(通俗说的命令行命令),拉取模板项目到本地

1.1 导言

我们平时经常会使用vue、angular、react等的脚手架,都可以达到如下效果

// 1. 全局安装对应的脚手架  "xxx-cli"  (不全局安装的话,只能在当前安装包下使用)
npm install -g xxx-cli// 2. 接下来直接就如"vue init"就可以直接拉取一个模板项目到我们的当前文件夹
vue init

这个效果挺好用的,假如我积累了一套框架,我不想每次重开项目都拷贝到其他文件夹来用;当别人需要的时候,别人又要从我这拷贝一份;或者是我每次都给别人一串别人基本记不住的git的url链接,这个太麻烦了
我希望能有一套脚手架,能像这些成熟的框架的脚手架一样直接把我想要的模板项目用最简短而有效的命令拉取到任何我想要获取的电脑的文件夹中,再有需要了,我还能继续拓展

// 全局安装脚手架
npm install -g snowcat
// 拉取预定义模板
snowcat init

本地效果演示:

其它机器上演示:


1.2 脚手架具体实现过程

先上组织结构和代码(结合思路和代码如果你已经懂了,省的还向下看),再从零开始讲实现方式和原理

1.1.1 0.0.1版本脚手架组织结构

1.1.2 实现0.0.1版本脚手架的完整代码

snowcat.js ==> 脚手架定义的所有命令的入口,这里暂时只有init命令

#!/usr/bin/env node
'use strict'
const program = require('commander')
program.version(require('../package').version )program.command('init').description('pull a new project').alias('i').action(() => {require('../command/init')()})program.parse(process.argv)if(!program.args.length){program.help()
}

init.js ==> init 命令的定义文件

'use strict'
const exec = require('child_process').exec
const projectUrl = 'https://github.com/screetBloom/wecat.js.git'module.exports = () => {console.log('this is my first commander >>>>>> ')let cmdStr = `git clone `+projectUrlexec(cmdStr, (error, stdout, stderr) => {if (error) {console.log(error)process.exit()}console.log('pull我们的项目已经成功了')process.exit()})}

package.json ==> 在package.json文件中声明整个文件包的可执行文件的位置

"bin": {"snowcat": "bin/snowcat.js"}

1.1.3 实现思路

上述的3个文件主要完成了2个最基本的事情

  • 1.自定义nodejs命令。在nodejs原本肯定是没有"snowcat"这种命令的,这个是我们自定义的
  • 2.用nodejs执行shell命令(通俗讲的命令行命令),这里主要是执行了git clone

那么我们现在先来尝试一下,如何自定义nodejs命令
在这里我们需要引入一个"commander.js"的npm包
先说明:不引入任何包都是可以完成我们上述的两件事,引入的主要原因有2个

  • 1.有了这个npm包,可以简化我们命令行的开发,把我们主要精力还是回归到框架开发上
  • 2.commander有大量的api,我们目前只是0.0.1版本,不依赖任何包来实现都是没有问题的,以后高版本1.0.0的拓展还是要用它的,这里我直接和大家说一下,也可以熟悉一下它的使用

我在这里补充一下不用任何依赖包的实现方式:

// PS.在nodejs中,可以直接用nodejs内置的全局变量process获取到你输入的命令的参数
// 现在我们直接就可以利用 process.argv来获取,如定义snowcat.js文件如下:
#!/usr/bin/env node
let run= function (para) {if(para[0] === '-test'){console.log('version is 1.0.0');}if(para[1] === '-host'){console.log('127.0.0.1');}
};console.log(process.argv)
run(process.argv.slice(2));

顶部的"#!/usr/bin/env node"的意思是 显式的声明这个文件用node来执行
执行snowcat.js文件

node snowcat.js
/*
输出结果如下:
[ '/usr/local/bin/node','/Users/chenwei/WebstormProjects/git_my/deep-in-vue/wim/test.js' ]
*/
node snowcat.js -test -host
/*
输出结果基本如下:
[ '/usr/local/bin/node','/Users/chenwei/WebstormProjects/git_my/deep-in-vue/wim/test.js','-test','-host' ]
*/

这里我想告诉大家的就是process.argv,这个东西很关键,可以拿到用户输入的命令,然后你就可以根据输入执行对应的函数就行了

先把 console.log(process.argv)注释了, 再来自定义指令试一试

node snowcat.js -test
/*
输出如下:
version is 1.0.0
*/
node snowcat.js -host/*输出如下:127.0.0.1*/

我写这个demo主要表示现在我们就可以直接根据参数来匹配对应执行的函数了,以上面的init.js文件为例
我们是先利用process.argv.slice(2) 获取到输入的参数,匹配一下执行对应的函数就行;纯node.js实现

argv返回的是一个不定长的数组,第一个是node.exe的路径,第二个是当前文件的路径,接下来是你命令后面跟的参数

nodejs中的process的官方说明文档在这
这里我们就顺着这个继续了,commander等等再说,对目前的我们来说也没到重要要偏说不可的地步

有没有注意到上面我们都是在js文件所在目录下直接"node snowcat.js -test"来执行js文件,我们该如何直接"snowcat -test"就执行js文件呢 ,也就是上面我们说的自定义nodejs命令
这个时候package.json就需要登场了

// 初始化一个package.json,相关信息自定义
npm init

在里面添加一行

"bin": {"snowcat": "snowcat.js"}

这个是什么意思呢: 简单说就是把命令名作为key,本地文件名作为value做一个映射。全局安装的时候,npm会把你定义的这个命令名"snowcat"对应的可执行文件安装到系统路径下,达到全局使用该命令的目的;本地安装的时候,会直接链接到'./node_modules/.bin/'

目前的配置信息应该基本如下:

{"name": "snowcat","version": "0.0.1","description": "my cli 0.0.1","main": "init.js","bin": {"snowcat": "snowcat.js"},"scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "wim_chen","license": "ISC"
}

现在我们来尝试本地的全局的运行 "snowcat" 命令,这里需要用到 "npm link",这里注意:是我们自己全局使用,给别人全局用可以发布到npm仓库

// 在当前的package.json中输入该命令
npm link

这个"npm link"主要是在我们本机的全局的"node_modules"目录中,生成一个符号链接"a symbolic link"指向我们当前文件夹

又因为我们在package.json中定义了"bin",指出了全局安装的时候命令"snowcat"对应的js文件
现在我们在本机的任何一个地方输入"snowcat -test -host"都会输出下述结果:

[ '/usr/local/bin/node','/Users/chenwei/Desktop/工作与兴趣/common_test/command/test_one/snowcat.js','-test','-host' ]
version is 1.0.0
127.0.0.1

想要进一步的达到如

npm install -g snowcat
// 执行我们目前的脚手架
snowcat -test -host

现在只需要做如下几步:

  • 1.注册一个npm账号,点击https://www.npmjs.com/ 直达npm官网
  • 2.给你的package.json里面的name写一个大家都没用过名字(snowcat你是别想了,很明显已经名花有主了)
  • 3.在你本地的package.json所在的路径下输入:"npm adduser",然后输入你的用户名、密码、邮箱
  • 4.输入 "npm publish"就将你的npm包发送到了npm仓库
  • 5.找个好朋友,让他安装一下你的包"npm install -g xxx",让他输入" snowcat -test -host"就可以打印出你写好的内容了,比如"我爱你"?

现在我们来按要求拉取我们的项目,用一开始的文件结构举例

先创建一下对应的文件

首先"npm init"我们的package.json文件,并设置"commander.js"依赖和合适的bin

{"name": "snowcat","version": "0.0.1","description": "my js cli 0.0.1","main": "index.js","bin": {"snowcat": "bin/snowcat.js"},"dependencies": {"commander": "^2.9.0"},"author": "wim_chen","license": "ISC"
}

这里先说明一下 commander.js的语法

program.command('init')       // 命令是 init.description('pull a new project')    // 命令的描述.alias('i')    // 命令别名,用init和i都行.action(() => {require('../command/init')()  // 执行init命令时要做什么,这里是执行init文件里导出的函数})

开始是编写我们的命令行入口文件,bin文件夹下的snowcat.js,也很简单

// 头部添加显示声明:本文件用node来执行
#!/usr/bin/env node
// 严格模式
'use strict'
// 引入 commander,用于处理自定义nodejs命令
const program = require('commander')
// 引用package.json里面的版本号来定义当前版本
program.version(require('../package').version )// 定义init命令,同时定义init命令的简化命令 i,包括命令的脚本文件所在路径
program.command('init').description('pull a new project').alias('i').action(() => {require('../command/init')()})// 这一句必不可少,作用是解析命令行参数argv,这里的process.argv是nodejs全局对象的属性
program.parse(process.argv)// 如果用户只是输入了 "snowcat"没带参数,就给他展示他能输入的所有命令
if(!program.args.length){program.help()
}

我们先来试一下,执行snowcat命令

node ./bin/snowcat.js 

显示如下,就是正确的,说明我们commander.js使用的很顺利

编写我们的 init.js

'use strict'
// 这个是node自带调用自窗口执行shell命令的方法,等会用
const exec = require('child_process').exec
module.exports = () => {console.log('this is my first commander >>>>>> ')
}

现在我们输入

node ./bin/snowcat.js  init

接下来我们来利用git来拉取我们的项目
编写init.js

'use strict'
const exec = require('child_process').exec
const projectUrl = 'https://github.com/screetBloom/wecat.js.git'module.exports = () => {console.log('this is my first commander >>>>>> ')// git命令,远程拉取项目并自定义项目名let cmdStr = `git clone `+projectUrl// 在nodejs中执行shell命令,第一个参数是命令,第二个是具体的回调函数exec(cmdStr, (error, stdout, stderr) => {if (error) {console.log(error)process.exit()}console.log('pull我们的项目已经成功了')process.exit()})}

现在我们再输入

node ./bin/snowcat.js  init

此时项目已经可以正确的拉取下来了,接下来我们来进行本地全局安装,在当前的package.json路径下输入"npm link"(可以本地全局使用了)
在其它路径下拉取项目

成功,那么现在我们把它放到npm仓库里,如果上一次你已经放进去0.0.1版本了,这次就需要修改版本号了,操作如下:

// 比如对最后一位进行修改:增1,命令,回车:
npm version patch
// 比如对第二位进行了修改:增1,命令:
npm version minor
// 比如对第一位进行了修改:增1,命令:
npm version major  // 查看所有的版本号:
npm view snowcat versions

最后我们再在其它机器上测试

// 全局安装脚手架
npm install -g snowcat
// 拉取预定义模板
snowcat init


0.0.1版本的脚手架分享到此结束

仿vue的前端自定义cmd命令拉取项目脚手架相关推荐

  1. 通过交互式命令从github拉取项目模板并创建新项目

    参考文档 Node.js 命令行程序开发教程 download-git-repo包从远程(GitHub, GitLab, Bitbucket)拉取文件到本地 commander.js包 在命令行中显示 ...

  2. 使用git命令拉取远程分支到本地分支

    文章目录 一.问题:使用插件拉取远程分支时,比较慢 二.使用命令拉取 三.建议push同样使用命令 一.问题:使用插件拉取远程分支时,比较慢 选中项目右键->git ->pull -> ...

  3. Git使用命令行拉取项目、提交代码

    一.拉取项目 1.打开GitHub,选择项目,复制项目地址 2.在电脑上新建一个项目文件夹,在文件夹里点击右键-->Git Bash Here,打开Git命令行 3.输入git clone + ...

  4. git拉取项目以及提交项目

    git拉取项目以及提交项目 1.打开cmd,键入cd d: d: cd project 输入git clone 你要拉区项目的地址 2.项目地址可以在gitee.com的项目代码那里去复制 3.提交项 ...

  5. Intellij IDEA 配置Git并拉取项目

    Git+Intellij IDEA是当前最流行的开发工具组合,相信用过的人都体会到了他们的强大和易用.在最近的一个项目中,因为项目组成员都是使用Intellij IDEA集成Git进行开发的,之前用的 ...

  6. 小程序开发(一)新建/拉取项目,配置远程仓库

    一.前期准备工作及工具 1.工具 微信开发者工具.Git 2.准备工作 相关开发工具的安装和配置工作请自行百度 二.新建或拉取远程项目 1.打开微信开发者工具(扫码登录等验证工作自行操作),选择小程序 ...

  7. git 拉取项目CMS管理后台项目

    git 拉取项目CMS管理后台项目 github 项目地址:luwei.web.study-ant-design-pro 企业内部项目地址:study.ant-design-pro 注:github ...

  8. Git拉取项目时报错: self signed certificate

    Git拉取项目时报错: self signed certificate 解决方法 git拉取代码或者项目报错self signed certificate 解决方法 运行Git Bash,执行配置命令 ...

  9. linux下安装svn并使用svn拉取项目

    一.安装svn,运行命令:apt-get install subversion 安装好后运行svn -version看看是否安装成功. 二.拉取项目,在自己的项目根目录运行命令:svn checkou ...

最新文章

  1. 五款漂亮的 GNOME 3.4 主题-PPA
  2. Java 小故事系列 导航
  3. 一场性能当道 优化为王的沙龙盛宴
  4. halcon模板匹配干扰边缘消除办法(最硬核方式)
  5. OpenStack_I版 1.准备过程
  6. warpaffine 旋转有一部分消失_如果月球消失了,会发生什么?我们的世界又将会变得怎么样?...
  7. [致歉]博客园升级造成的问题
  8. c++ 常用字符串封装函数
  9. Bailian2870 求矩阵的加法【矩阵】
  10. android+默认存储,Android 数据存储之SP存储,内部存储,外部存储
  11. 一个简单的互斥量与条件变量例子
  12. win10 安装 cognos 10.2.0
  13. 英文操作系统中的乱码问题及其它
  14. Kiwi Syslog日志服务器的安装及配置使用
  15. PS亮度蒙版插件TKActions V5 Mac版
  16. PAT乙级真题1093 || 字符串A+B(详解,C/C++示例,测试点分析)
  17. 小米手机如何更换铃声和微信提示音
  18. 别忽悠我,征信真的有黑名单吗?
  19. Solidity Integer Overflow and Underflow
  20. ubuntu18.04 安装 CARLA0.9.10

热门文章

  1. Java反射机制应用实践
  2. 编辑器性能测试:Atom 、VS Code、Sublime Text
  3. MySQL 覆盖索引
  4. Java访问指示符 访问修饰符
  5. 给在读研究生的一封信(强烈推荐)
  6. 【Spark 深入学习 04】再说Spark底层运行机制
  7. CTO下午茶: 没有安全,一切创新都是套路
  8. Glide核心设计一:皮皮虾,我们走
  9. MYSQL如何导出存储过程和触发器?
  10. php 时间 (年,月,星期,天,小时,秒)的查找