445b531f38917d836582a9aa2e9c0aa7.jpeg


在讲解脚手架之前,我们先来看看目录结构吧:

  1. =================
  2. |__ bin
  3. |__ index.js
  4. |__ command
  5. |__ add.js
  6. |__ delete.js
  7. |__ init.js
  8. |__ list.js
  9. |__ node_modules
  10. |__ package.json
  11. |__ templates.json

首先,新建pakage.json文件,写入依赖并且执行npm install

{
  "dependencies": {//必须依赖
    "chalk": "^1.1.3",
    "co": "^4.6.0",
    "co-prompt": "^1.0.0",
    "commander": "^2.9.0"
  },
  "name": "templates_wct",//模板名称,用于npm install name
  "version": "1.0.1",//发布时填写的版本号
  "description": "a tool service for react-ssr",//描述
  "main": "index.js",//入口文件名称
  "bin": {
    "snowcat": "bin/index.js"//执行名称,配置后只需:snowcat init 便可初始化。 
  },
  "author": "wct",
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Windseek/react-ssr-cli.git"
  },
  "keywords": [
    "react",
    "react-ssr",
    "wind-ssr",
    "react-ssr-cli"
  ],
  "bugs": {
    "url": "https://github.com/Windseek/react-ssr-cli/issues"
  },
  "homepage": "https://github.com/Windseek/react-ssr-cli#readme"
}

入口文件

在根目录下建立\bin文件夹,在里面建立一个index.js文件。这个bin\index.js文件是整个脚手架的入口文件,所以我们首先对它进行编写。

首先是一些初始化的代码:

#!/usr/bin/env node
const { resolve } = require('path')
const program = require('commander')
process.env.NODE_PATH = resolve(__dirname, '../node_modules/')
const { version } = require(resolve(__dirname, '../package.json'))
// const version = require('../package');
// process.env.NODE_PATH = __dirname + '/../node_modules/';
program
  .version(version)

program
  .usage('<commands>')

program
  .command('add')
  .description('Add a new template')
  .alias('a')
  .action(() => {
    require('../commands/add')()
  })

program
  .command('list')
  .description('List all templates')
  .alias('l')
  .action(() => {
    require('../commands/list')()
  })

program
  .command('delete')
  .description('Delete a template')
  .alias('d')
  .action(() => {
    require('../commands/delete')()
  })

program
  .command('init')
  .description('Generate a new project')
  .alias('i')
  .action(() => {
    require('../commands/init')()
  })

program.parse(process.argv)

if(!program.args.length){
  program.help()
}

从前文的架构图中我们可以看到,在根目录下创建一个/commands文件,其下有四个js文件,init,list,add,delete

在根目录下新建一个模板templates.json,用于存放模板信息;

{"tpl":{
  "react":{"url":"https://github.com/Windseek/reactssr.git","branch":"master"},
    }
}

模板初始化:init

'use strict'
const exec = require('child_process').exec;//可运行复杂的命令
const co = require('co');//异步控制流程模块,和es6标准Promise类似,基于 ES6 的 generator 和 yield,属于node圈
const prompt = require('co-prompt')
const config = require('../templates')
const chalk = require('chalk');//为了使输出不再单调,添加文字背景什么的,改变字体颜色什么的
module.exports = () => {
    co(function *() {
      // 处理用户输入
      let tplName = yield prompt('Template name (you can input one like react, vue, angular): ')
      let projectName = yield prompt('Project name: ')
      let gitUrl,branch;
      console.log(config.tpl);
      if (!config.tpl[tplName]) {
        console.log(chalk.red('\n × Template does not support!'))
        process.exit()
      }
      gitUrl = config.tpl[tplName].url
      branch = config.tpl[tplName].branch

      // git命令,远程拉取项目并自定义项目名
      let cmdStr = `git clone ${gitUrl} ${projectName} && cd ${projectName} && git checkout ${branch}`

      exec(cmdStr, (error, stdout, stderr) => {
        if (error) {
          console.log(error)
          process.exit()
        }
        console.log(chalk.green('\n √ Generation completed!'))
        console.log(`\n cd ${projectName} && npm install \n`)
        process.exit()
      })
    })
}

模板新增:add——->模板信息写进templates.json

'use strict'
const co = require('co')
const prompt = require('co-prompt')
const config = require('../templates')
const chalk = require('chalk')
const fs = require('fs')
module.exports = () => {
  co(function *() {
    // 分步接收用户输入的参数
    let tplName = yield prompt('Template name: ')
    let gitUrl = yield prompt('Git https link: ')
    let branch = yield prompt('Branch: ')

    // 避免重复添加
    if (!config.tpl[tplName]) {
     let objConfig = {};
      objConfig.url = gitUrl.replace(/[\u0000-\u0019]/g, '') // 过滤unicode字符
      objConfig.branch = branch
      config.tpl[tplName] = objConfig
    } else {
      console.log(chalk.red('Template has already existed!'))
      process.exit()
    }

    // 把模板信息写入templates.json
    fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config), 'utf-8', (err) => {
      if (err) console.log(err)
      console.log(chalk.green('New template added!\n'))
      console.log(chalk.grey('The last template list is: \n'))
      console.log(config)
      console.log('\n')
      process.exit()
    })
  })
}

模板删除:delete


'use strict'
const co = require('co')
const prompt = require('co-prompt')
const config = require('../templates')
const chalk = require('chalk')
const fs = require('fs')

module.exports = () => {
  co(function *() {
    // 接收用户输入的参数
    let tplName = yield prompt('Template name: ')

    // 删除对应的模板
    if (config.tpl[tplName]) {
      config.tpl[tplName] = undefined
    } else {
      console.log(chalk.red('Template does not exist!'))
      process.exit()
    }

    // 写入template.json
    fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config),     'utf-8', (err) => {
      if (err) console.log(err)
      console.log(chalk.green('Template deleted!'))
      console.log(chalk.grey('The last template list is: \n'))
      console.log(config)
      console.log('\n')
      process.exit()
    })
  })
}

查看模板列表:list

'use strict'
const config = require('../templates')

module.exports = () => {
  console.log(config.tpl)
  process.exit()
}

全局使用,在根目录下:

确认设置 package.json下的bin为:

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

执行:npm link

执行snowcat 测试结果:

Usage: scion <command>

  Options:

    -h, --help     output usage information
    -V, --version  output the version number

  Commands:

    add|a      Add a new template
    list|l     List all the templates
    init|i     Generate a new project
    delete|d   Delete a template

写好了需要发布一下喽:npm账号注册(https://www.npmjs.com/

1、npm login,填写用户名,密码
2、修改package.json里version
3、npm publish
4、去https://www.npmjs.com/上看看成功没有

相关说明:

1、package.json里定义bin的位置
2、index里定义bin命令指定执行的代码
3、init里执行shell,去git上拿代码模板

安装和初始化:

1、npm install templates_wct -g
2、snowcat init
3、选择要使用的模板,react,angular和vue

注: 原址请参考CSDN:(https://blog.csdn.net/fengyinchao/article/details/52168619)