根据命令行交互提供不同的初始化文件

最近在自制cli脚手架工具,面临的一个场景是根据用户命令行的交互行为定制不同初始化文件。
想了很久,决定借鉴express-generator的使用inquirer.js和模板引擎来实现此需求。
下面以几个简单的示例来实现此需求。

模板引擎

Node中模板引擎常用于渲染特定标准的HTML字符串,既然是字符串,我们就可以利用fs.writeFileSync()同样将定制化的HTML字符串写入文件中。
点击查看EJS语法

模板文件

新建一个app.js.ejs作为入口文件,添加如下代码:

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = <%= body %>;
});

app.listen(<%= port %>);

命令行交互文件

inquirer.js支持多种命令行交互类型,这里我们简单以input类型为例:
新建index.js作为命令行交互文件,添加如下代码:

#!/usr/bin/env node
const inquirer = require('inquirer')
const fs = require('fs')
const ejs = require('ejs')
const path = require('path')
const util = require('util')

inquirer.prompt([{
  type:'input',
  name: 'port',
  message: '请输入你想监听的端口'
}, {
  type:'input',
  name: 'body',
  message: '你想输出的内容'
}]).then(answers => {
  const app = loadTemplate()
  Object.assign(app.locals, answers)
  fs.writeFileSync('./app.js', app.render(), 'utf-8')
})
function loadTemplate() {
  const contents = fs.readFileSync(path.join(__dirname, './app.js.ejs'), 'utf-8')
  const locals = Object.create(null)

  function render() {
    return ejs.render(contents, locals, {
      escape: util.inspect
    })
  }
  return {
    locals,
    render
  }
}