用Node.js简单写个脚手架

版权声明:转载需注明出处 https://blog.csdn.net/samfung09/article/details/82833798

1、初始化

创建项目目录sam-cli

npm init -y 初始化项目

创建index.js文件

使用node开发命令行工具所执行JavaScript脚本必须在顶部加入 #!/usr/bin/env node 声明该命令行脚本是node.js写的

#!/usr/bin/env node
// 使用node开发命令行工具所执行JavaScript脚本必须在顶部加入 #!/usr/bin/env node 声明

console.log('hello world');

在package.json文件中追加"bin": {"sam": "index.js"}

{
  "name": "sam-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bin": {
    "sam": "index.js"
  }
}

命令行执行npm link 来将sam命令链接到全局

这时在任何目录下执行命令行sam就会输出

2、命令行工具参数设计

sam -h|--help 查看使用帮助
sam -V|--version 查看工具版本号
sam list 列出所有可用模板
sam init <template-name> <project-name> 基于指定模板进行项目初始化

使用process.argv获取命令行参数(方法之一)

index.js文件中console.log(process.argv)

命令行执行sam --help,输出

3、使用commander处理命令行参数

npm install commander

index.js文件

#!/usr/bin/env node

const program = require('commander');

// sam -V|--version
program.version('0.1.0');  // -v|--version时输出版本号0.1.0

// sam init <template> <project>
program
    .command('init <template> <project>')
    .description('初始化项目模板')
    .action((templateName, projectName) => {
        console.log(templateName, projectName);
    })

// sam list
program
    .command('list')
    .description('查看所有可用模板')
    .action(() => {
        console.log(`
            a   a模板
            b   b模板
            c   c模板
        `)
    })

program.parse(process.argv);

这时命令行执行

4、github上创建模板仓库

这里我创建了tpl-a和tpl-b两个模板仓库

5、使用download-git-repo帮助从github下载模板

npm install download-git-repo

index.js文件download部分代码

const download = require('download-git-repo');
// 可用模板
const templates = {
    'tpl-a': {
        url: 'https://github.com/samfung09/tpl-a',
        downloadUrl: 'https://github.com:samfung09/tpl-a#master',
        description: 'sam-cli脚手架测试模板a'
    },
    'tpl-b': {
        url: 'https://github.com/samfung09/tpl-b',
        downloadUrl: 'https://github.com:samfung09/tpl-b#master',
        description: 'sam-cli脚手架测试模板b'
    }
}

// sam -V|--version
program.version('0.1.0');  // -v|--version时输出版本号0.1.0

// sam init <template> <project>
program
    .command('init <template> <project>')
    .description('初始化项目模板')
    .action((templateName, projectName) => {
        // console.log(templateName, projectName);
        let {downloadUrl} = templates[templateName];        
        //第一个参数是github仓库地址,第二个参数是创建的项目目录名,第三个参数是clone
        download(downloadUrl, projectName, {clone: true}, err => {
            if(err){
                console.log('下载模板出错');
            }else{
                console.log('下载模板成功');
            }
        })
    })

这里需要注意的是download地址跟github仓库地址有点出入,比如github仓库地址是https://github.com/xxx/xxx而下载地址是https://github.com:xxx/xxx

这时命令行执行sam init tpl-a aaa就会在当前目录下创建aaa项目目录里面下载好了tpl-a模板的所有文件

6、使用inquirer进行命令行答询

npm install inquirer

在模板仓库中创建package.json文件

7、使用handlebars修改package.json

npm install handlebars

8、使用ora在命令行中显示加载状态

npm install ora

9、使用chalk和log-symbols增加命令行输出样式

npm install chalk log-symbols

最后index.js文件代码如下

#!/usr/bin/env node

const program = require('commander');       //设计命令行
const download = require('download-git-repo');      //github仓库下载
const inquirer = require('inquirer');       //命令行答询
const handlebars = require('handlebars');       //修改字符
const ora = require('ora');         //命令行中加载状态标识
const chalk = require('chalk');     //命令行输出字符颜色
const logSymbols = require('log-symbols');      //命令行输出符号
const fs = require('fs');
// 可用模板
const templates = {
    'tpl-a': {
        url: 'https://github.com/samfung09/tpl-a',
        downloadUrl: 'https://github.com:samfung09/tpl-a#master',
        description: 'sam-cli脚手架测试模板a'
    },
    'tpl-b': {
        url: 'https://github.com/samfung09/tpl-b',
        downloadUrl: 'https://github.com:samfung09/tpl-b#master',
        description: 'sam-cli脚手架测试模板b'
    }
}

// sam -V|--version
program.version('0.1.0');  // -v|--version时输出版本号0.1.0

// sam init <template> <project>
program
    .command('init <template> <project>')
    .description('初始化项目模板')
    .action((templateName, projectName) => {
        // console.log(templateName, projectName);
        let {downloadUrl} = templates[templateName];        
        //下载github项目,下载墙loading提示
        const spinner = ora('正在下载模板...').start();        
        //第一个参数是github仓库地址,第二个参数是创建的项目目录名,第三个参数是clone
        download(downloadUrl, projectName, {clone: true}, err => {
            if(err){
                spinner.fail('项目模板下载失败');
            }else{
                spinner.succeed('项目模板下载成功');
                //命令行答询
                inquirer.prompt([
                    {
                        type: 'input',
                        name: 'name',
                        message: '请输入项目名称',
                        default: projectName
                    },
                    {
                        type: 'input',
                        name: 'description',
                        message: '请输入项目简介',
                        default: ''
                    },
                    {
                        type: 'input',
                        name: 'author',
                        message: '请输入作者名称',
                        default: ''
                    }
                ]).then(answers => {
                    //根据命令行答询结果修改package.json文件
                    let packsgeContent = fs.readFileSync(`${projectName}/package.json`, 'utf8');
                    let packageResult = handlebars.compile(packsgeContent)(answers);
                    fs.writeFileSync(`${projectName}/package.json`, packageResult);
                    //用chalk和log-symbols改变命令行输出样式
                    console.log(logSymbols.success, chalk.green('模板项目文件准备成功'));
                })
            }
        })
    })

// sam list
program
    .command('list')
    .description('查看所有可用模板')
    .action(() => {
        console.log(`
            tpl-a   sam-cli脚手架测试模板a
            tpl-b   sam-cli脚手架测试模板b
        `)
    })

program.parse(process.argv);

10、npm发布

登录npm(要有npm账号)

npm login

发布(项目目录下)

npm publish

猜你喜欢

转载自blog.csdn.net/samfung09/article/details/82833798