一直想建一个自己公司自用的脚手架,可以方便的快速开发。于是开始看vue-cli的源码和一些网上的教程。发现,一款脚手架其实很简单,主要原理就是从远程下载一个模板来新建一个项目。同时提供了一系列的交互来动态的更改模板。
下面先将建立一款脚手架可能用到插件及其使用方法列出:

1、commander

用来编写指令和处理命令行
安装commander:
npm install commander --save

主要api解析

(1)version

作用:定义版本号
用法:.version('0.0.1', '-v --version')
参数解析:

  • 版本号(必须)
  • 自定义标志(可省略):默认为-V和--version

(2)option

作用:定义命令选项
用法:.option('-n --name<path>', 'name description', 'default name')
参数解析:

  • 自定义标志<必须>:分为长短标识,中间用逗号、竖线或者空格分割;标志后面可跟必须参数或可选参数,前者用 <> 包含,后者用 [] 包含
  • 选项描述<可省略>:在使用 --help 命令时显示标志描述
  • 默认值<可省略>

例子:

program
  .version('0.1.0', '-v, --version')
  .option('-i, --init', 'init something')
  .option('-g, --generate', 'generate something')
  .option('-r, --remove', 'remove something');

(3)command

作用:添加命令名称
用法:.command('rmdir <dir> [otherDirs...]', 'install description', opts)
参数解析:

  • 命令名称<必须>:命令后面可跟用 <> 或 [] 包含的参数;命令的最后一个参数可以是可变的,像实例中那样在数组后面加入 ... 标志;在命令后面传入的参数会被传入到 action 的回调函数以及 program.args 数组中
  • 命令描述<可省略>:如果存在,且没有显示调用action(fn),就会启动子命令程序,否则会报错
  • 配置选项<可省略>:可配置noHelp、isDefault等

(4)description

作用:定义命令的描述
用法:.description('rmdir desc')

(5)action

作用:定义命令的回调函数
用法:.action(fn)

(6)parse

作用:解析process.argv,设置options以及触发commands
用法:.parse(process.argv)

(7)on
作用:自定义监听事件
用法:.on('name', fn)
例子:

// 必须在.parse()之前,因为node的emit()是即时的
program.on('--help', function(){
 console.log('  Examples:');
  console.log('');
  console.log('    this is an example');
  console.log('');
});
program.on('option:verbose', function(){
  process.env.VERBOSE = this.verbose;
})

//error on unkown commands
program.on('command:*', function(){
  console.error('Invalid command: %s\nSee --help for a list of available commands.', program.args.join(' '))
  process.exit(1);
})

综合用法示例

// 引入依赖
var program = require('commander');
 
// 定义版本和参数选项
program
  .version('0.1.0', '-v, --version')
  .option('-i, --init', 'init something')
  .option('-g, --generate', 'generate something')
  .option('-r, --remove', 'remove something');
 
// 必须在.parse()之前,因为node的emit()是即时的
program.on('--help', function(){
 console.log('  Examples:');
  console.log('');
  console.log('    this is an example');
  console.log('');
});
 
program.parse(process.argv);
 
if(program.init) {
  console.log('init something')
}
 
if(program.generate) {
  console.log('generate something')
}
 
if(program.remove) {
  console.log('remove something')
}
var program = require('commander')
program
  .version('0.1.1')
  .command('rmdir <dir> [otherDirs...]')
  .action(function(dir, otherDirs){
    console.log('rmdir %s', dir)
    if(otherDirs){
        otherDirs.forEach(function(oDir){
          console.log('rmdir %s', oDir)
        })
    }
  })
  
program.parse(process.argv)

执行 node index.js rmdir ./test aaa

参考链接:
https://blog.csdn.net/qq_4012...
https://www.cnblogs.com/miran...

2、inquirer

用来进行交互式命令行
安装:npm install inquirer --save
语法结构:

const inquirer = require('inquirer');

const promptList = [
    // 具体交互内容
];

inquirer.prompt(promptList).then(answers => {
    console.log(answers); // 返回的结果
})

基本api
type:表示提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;
name: 存储当前问题回答的变量;
message:问题的描述;
default:默认值;
choices:列表选项,在某些type下可用,并且包含一个分隔符(separator);
validate:对用户的回答进行校验;
filter:对用户的回答进行过滤处理,返回处理后的值;
transformer:对用户回答的显示效果进行处理(如:修改回答的字体或背景颜色),但不会影响最终的答案的内容;
when:根据前面问题的回答,判断当前问题是否需要被回答;
pageSize:修改某些type类型下的渲染行数;
prefix:修改message默认前缀;
suffix:修改message默认后缀。

使用示例

var inquirer = require('inquirer');
const promptList = [{
    type: 'input',
    message: '设置一个用户名',
    name: 'name',
    default: 'test_user'
},{
    type: 'input',
    message: '请输入手机号',
    name: 'phone',
    /*validate: function(val){
        if(val.match(/\d{11}/g)){
            //return val
        }
        return "请输入11位数字"
    }*/
},{
    type: 'confirm',
    message: '是否启用监听',
    name: 'watch',
    prefix: '前缀',
    suffix: '后缀',
    when: function(answers){
        //当watch为true时,开始提问
        return answers.watch
    }
},{
    type: 'list',
    message: '请选择一种水果',
    name: 'fruit',
    choices:[
        "Apple",
        "Pear",
        "Banana"
    ], 
    filter: function(val){
        //将回答变为小写
        return val.toLowerCase()
    }
}]

inquirer.prompt(promptList).then(answers => {
    // 回调函数,answers 就是用户输入的内容,是个对象
    console.log(answers)
})

3、chalk

设置控制台输出内容的样式
使用示例

const chalk = require('chalk')
//控制颜色
console.log(chalk.green('success'))
console.log(chalk.blue.bgRed.bold('Hello world'))
console.log(chalk.underline.bgBlue('lala'))

4、ora

提供一个加载中效果
使用示例

const ora = require('ora')
//出现加载效果
let spinner = ora('downloading template')
spinner.start()
//加载失败效果
spinner.fail()
//结束加载效果
spinner.succeed()

5、download-git-repo

下载远程模板:支持github、gitlab等
使用语法:

const download = require('download-git-repo')
download(repository, destination, options, callback)

repository为远程仓库地址,destination为下载的文件路径,默认当前目录,options时一些选项,比如clone:boolean表示用http下载还是git clone的形式下载

6、metalsmith

静态网站生成器,metalsmith的所有逻辑都是由插件处理的,只需要将它们链接在一起。
官网:https://metalsmith.io/
官网示例:

var Metalsmith \= require('metalsmith');

var markdown \= require('metalsmith-markdown');

var layouts \= require('metalsmith-layouts');

var permalinks \= require('metalsmith-permalinks');

Metalsmith(\_\_dirname)

.metadata({

title: "My Static Site & Blog",

description: "It's about saying »Hello« to the World.",

generator: "Metalsmith",

url: "http://www.metalsmith.io/"

})

.source('./src')

.destination('./build')

.clean(false)

.use(markdown())

.use(permalinks())

.use(layouts({

engine: 'handlebars'

}))

.build(function(err, files) {

if (err) { throw err; }

});

handlebars

一个简单高效的语义化模板构建引擎


stray
132 声望10 粉丝