ZhenHe17 / blog

个人博客,希望能让各位看官有所收获,喜欢可以 star || watch ^_^ 🎉

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

百行代码实现模板生成工具

ZhenHe17 opened this issue · comments

在团队中我们会需要一个快速生成定制化模板的工具,这里记录下具体实现。

主要技术栈:nodeejs
代码仓库: 快速生成 docker & nest 模板

工具功能

根据用户的输入,灵活快速地生成项目模板文件

获取命令行参数

const commander = require('commander')

const program = new commander.Command()
program.parse(process.argv)
if (program.args.length > 1) {
    console.log('参数错误 使用示例:cdna my-nest-app')
    return false
}

// program.args: [ my-nest-app ]
console.log(program.args, '命令行输入参数')

获取用户输入

const readlineSync = require('readline-sync')
const isInstallMysql = readlineSync.keyInYN(`需要在项目里安装 MySQL 吗?)`)
// isInstallMysql: true / false
console.log(isInstallMysql, '是否安装 MySQL')

生成项目模板

可以通过多种方式生成模板,这里通过下载 git 仓库生成,方便模板的维护和修改

const download = require('download-git-repo')
const downloadRepoUrl = 'ZhenHe17/docker-nest-template'
const targetFoldName = program.args[0] || 'my-nest-app'

download(downloadRepoUrl, `./${targetFoldName}`, (err) => {
    if (err) {
        console.error(err)
    } else {
        renderTemplate(isInstallMysql)
    }
})

根据用户输入处理模板

模板文件已经下载在当前目录了。下面根据用户输入的参数,用 ejs 处理模板:

// renderTemplate.js

const ejs = require('ejs')
const fs = require('fs')
const path = require('path')

const readDirAndRender = entry => {
    const dirInfo = fs.readdirSync(entry);
    dirInfo.forEach(item=>{
        const location = path.join(entry,item);
        const info = fs.statSync(location);
        if(info.isDirectory()){
            // console.log(`dir:${location}`);
            readDirAndRender(location);
        }else{
            // console.log(`file:${location}`);
            ejs.renderFile(location, { isInstallMysql }, {}, function(err, str){
                const notEmpty = /\S/.test(str)
                if (notEmpty) {
                    const data = new Uint8Array(Buffer.from(str));
                    fs.writeFile(location, data, (err) => {
                        if (err) throw err;
                    });
                } else {
                    fs.unlink(location, (err) => {
                        if (err) throw err;
                    });
                }
            });
        }
    })
}

const entry = `./${target}`
readDirAndRender(entry)

递归的使用 ejs.renderFile 处理模板中的所有文件

// package.json
<% if (isInstallMysql) { %>
    "mysql": "2.17.1",
    "typeorm": "0.2.20",
<% } %>

ejs 处理后,如果用户选择安装 MySQL ,则 package.json 的依赖中会加上 mysql 和 typeorm 的依赖。

示例

快速生成 docker & nest 模板

npm i create-docker-nest-app -g
cdna my-app

其他

  • 可以把工具上传到 npm 上,方便安装和使用
  • package.json 中的 bin 字段指定本工具在命令行中的调用命令
  • 可以使用 chalk 库定制控制台输出文字的样式