使用EJS实现一键自动化生成代码模版

前言:在使用Koa2写毕设后端API的时候,每写一个接口,需要分别在routercontrollerservice三个文件夹下分别创建文件,在接口很多的情况下,每次在三个文件夹下分别创建对应的文件,是一件很没有效率的事情,那有没有什么比较好的解决方案么?写一个自动生成代码文件的脚本!!!

结合这篇:使用Koa2写接口的一般步骤进行阅读更佳

1、使用到的库

  • ejs:是一套简单的模板语言,帮你利用普通的 JavaScript代码HTML 页面;

    • npm install ejs -D

    • <% ‘脚本’ 标签,用于流程控制,无输出。

    • <%_ 删除其前面的空格符

    • <%= 输出数据到模板(输出是转义 HTML 标签)

    • <%- 输出非转义的数据到模板

    • <%# 注释标签,不执行、不输出内容

    • <%% 输出字符串 ‘<%’

    • %> 一般结束标签

    • -%> 删除紧随其后的换行符

    • _%> 将结束标签后面的空格符删除

  • chalk:它是一个简单实用的控制台格式渲染工具,可以自由定义颜色、背景色以及格式等;

    • npm install chalk -D
    • 效果如下:

  • inquirer:它是一个用户与命令行交互的工具;
    • npm install inquirer -D
    • 效果如下:

  • change-case:change-case包的主要作用是将字符串在骆驼式格式(camelCase),帕斯卡格式(PascalCase)首字母格式(Title Case),蛇底式格式(snake_case),小写格式(lowercase),大写格式(UPPERCASE),常量格式(CONSTANT_CASE)之间转换。
    • npm install change-case -D

2、目录结构

2.1、模版代码:

  • 在根目录下创建scripts文件夹,在其中分别创建controller-templaterouter-templateservice-template三个文件夹,分别是控制器、路由层、服务层(操作数据库的议一些方法)。其中.ejs文件就是模版代码
  • controller.ejs
const <%- fileName %>Service = require('../service/<%- fileName %>.service')

class <%- fileName %>Controller {

}

module.exports = new <%- fileName %>Controller();
  • router.ejs
const Router = require('koa-router');

// 具体的处理逻辑
const {

} = require('../controller/<%- fileName %>.controller');

const <%- fileName %>Router = new Router({
  prefix: '/api/<%- fileName %>'
});

<%- fileName %>Router.post('/', );

module.exports = <%- fileName %>Router;
  • service.ejs
const connection = require('../app/database');

class <%- fileName %>Service {
  
}

module.exports = new <%- fileName %>Service();

2.2、入口代码

  • new-file.js
const chalk = require('chalk'); // 终端样式库
const inquirer = require('inquirer'); // 命令行用户交互库
const fs = require('fs');
const path = require('path');
const ejs = require('ejs'); // JavaScript模版引擎库
const changeCase = require('change-case'); // 字符串格式切换库

const fileNameReg = /^[a-z]*$/;
async function getFileName() {
  let fileName = process.argv[2]; // 获取命令行输入的参数

  if (!fileName) {
    const answers = await inquirer.prompt([{
      type: 'input',
      name: 'fileName',
      message: chalk.green('请输入要创建的文件名称(小写字母形式,如test): ')
    }]);
    if (answers.fileName) {
      fileName = answers.fileName;
    } else {
      fileName = await getFileName();
    }
  }

  if (!fileNameReg.test(fileName)) {
    fileName = await getFileName();
  }

  return fileName;
}

getFileName().then(fileName => {
  const pascalFileName = changeCase.pascalCase(fileName); // 开头字母转大写

  // 在src/controller目录下创建一个子目录,用于存放file的核心代码
  const controllerFile = path.resolve(__dirname, `../src/controller/${fileName}.controller.js`);
  // 在src/router目录下创建一个子目录,用于存放file的核心代码
  const routerFile = path.resolve(__dirname, `../src/router/${fileName}.router.js`);
  // 在src/service目录下创建一个子目录,用于存放file的核心代码
  const serviceFile = path.resolve(__dirname, `../src/service/${fileName}.service.js`);

  // 检测是否存在该文件
  const exists = fs.existsSync(controllerFile) && fs.existsSync(routerFile) && fs.existsSync(serviceFile); 

  // 拿到模版代码
  // 方式一
  // const controllerCode = fs.readFileSync(path.resolve(__dirname, "./controller-template/controller.ejs"));

  // const routerCode = fs.readFileSync(path.resolve(__dirname, "./router-template/router.ejs"));

  // const serviceCode = fs.readFileSync(path.resolve(__dirname, "./service-template/service.ejs"));

  // 方式二
  const controllerTemplate = path.resolve(__dirname, "./controller-template/controller.ejs");

  const routerTemplate = path.resolve(__dirname, "./router-template/router.ejs");

  const serviceTemplate = path.resolve(__dirname, "./service-template/service.ejs");

  if (exists) {
    console.log(`${chalk.red(`文件 ${chalk.bold(fileName)} 代码或文档已存在,请勿重复添加!`)}`);
    return;
  } else {
    /**
     * 方式一
     * ejs.render(str, data, options);
     *  => 输出渲染后的 HTML 字符串
     */
    // let controllerResult = ejs.render(controllerCode.toString(), {fileName: pascalFileName});
    // let routerResult = ejs.render(routerCode.toString(), {fileName: fileName});
    // let serviceResult = ejs.render(serviceCode.toString(), {fileName: pascalFileName});

    // fs.writeFileSync(controllerFile, controllerResult)
    // fs.writeFileSync(routerFile, routerResult)
    // fs.writeFileSync(serviceFile, serviceResult)

    /**
     * 方式二
     * ejs.renderFile(filename, data, options, function(err, str){
     *   // str => 输出渲染后的 HTML 字符串
     * });
     */
     ejs.renderFile(controllerTemplate, {
      fileName: pascalFileName
    }, null, function (_, str) {
      fs.writeFileSync(controllerFile, str);
    });

     ejs.renderFile(routerTemplate, {
      fileName: fileName
    }, null, function (_, str) {
      fs.writeFileSync(routerFile, str);
    });

     ejs.renderFile(serviceTemplate, {
      fileName: pascalFileName
    }, null, function (_, str) {
      fs.writeFileSync(serviceFile, str);
    });

  }
})

2.3、使用命令生成三个模版

  • package.json文件中的script内添加"new-file": "node ./scripts/new-file.js",在命令终端输入npm run new-file xxx(xxx是你所创建文件的名字)

  • 命令有两种使用方法

3、成果展示

3.1、方法一

  • 例如我需要创建一个测试的接口,那么我可以这样做:
  • 终端输入:npm run new-file test,如下所示:

  • 最终会创建三个文件,分别是test.controller.jstest.router.jstest.service.js

  • 如果再次输入相同的命令,就会提示该文件已经存在
  • 红色字体就是chalk库的作用,控制器格式渲染
  • console.log(`${chalk.red(`文件 ${chalk.bold(fileName)} 代码或文档已存在,请勿重复添加!`)}`);

3.2、方案二

  • 直接使用命令npm run new-file,再输入需要创建的文件名称
  • 这个是inquirer库的作用:用户与命令行交互的工具(感觉是不是很熟悉,很像使用Vue脚手架创建项目的界面,vue-cli就是使用这个库)

结语

  • 以上就是一个目录结构比较简单的自动化生成代码模版方式;
  • 目录比较复杂的:比如在组件库中使用,通常封装一个组件,需要在多处文件夹中新建文件,使用脚本自动化生成代码模版的方式,就能大大提高封装组件的效率
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值