使用yeoman根据自己的模板创建一个脚手架

介绍

  1. 本文使用的模板并不是通用模板~,是自己构建的模板。内部具体如何选择组件模板逻辑就没有了,仅仅相当于入门demo实现流程。
  2. 有兴趣学习脚手架的话yo还是不错的,走完本文逻辑可以试试看抽成自己项目,然后引用至公司~
  3. 加油!
  4. 参考资料:
  5. yeoman官网
  6. node官网文档选择

实现过程

  1. 创建文件夹(xxx/csdn),然后执行npm init -y
    (1)注意name必须为 generator-xxx ; (xxx为你自定义名字,这里我们以 generator-app来举例子)
    在这里插入图片描述

  2. 再创建 (xxx/csdn/generators/app)(xxx/csdn/generators/app/index.js)
    xxx/csdn/generators/app/index.js内填入以下内容

    const Generator = require('yeoman-generator');
    module.exports = class extends Generator {
    	method() {
    		console.log('我执行了')
    	}
    }
    
  3. 下载需要的依赖
    (1)yeoman-generator[ npm install --save yeoman-generator ]
    (2)inquirer[ npm i inquirer@8.0.0 ]
    (3)ejs[npm i ejs]
    (4)yo[ npm install -g yo ]
    (5)generator-webapp[ npm install -g generator-webapp ]

做完以上操作后你的界面结构应该是这样的(你的yeoman环境准备完毕)

在这里插入图片描述

  1. 接下来进入cmd小黑窗运行 npm link命令;(不懂 npm link 意思的可以去看看我这篇文章

  2. 然后任意找一个地方建立一个文件夹(d:/xxxxxxxx/use),cmd进入小黑窗然后执行yo app 命令(记住你一开始使用的 generator-app则运行这个命令,如果不是则yo xxx;(xxx为你自定义的名字)
    如果执行完毕后你出现以下情况,则说明你成功了一半了~
    在这里插入图片描述

  3. 创建 xxx/csdn/utils/readFilePath.js文件,填入以下代码,代码介绍代码里有~

/**
 * fileDisplay(url, callback)
 * @param url: 你即将读取的文件夹路径
 * @param callback: 回调函数
 */

// node fs模块
const fs = require('fs');
// node path模块
const path = require('path');
// 收集所有的文件路径
const arr = [];
let timer = null;
class firstUrl {
  _url = '';
  constructor() {
    this.get()
  }
  get(url) {
    if (this._url) return this._url
    this._url = url
    return url
  }
}
const init = new firstUrl();
const fileDisplay = (url, cb) => {
  init.get(url);
  const filePath = path.resolve(url);
  //根据文件路径读取文件,返回文件列表
  fs.readdir(filePath, (err, files) => {
    if (err) return console.error('Error:(spec)', err)
    files.forEach((filename) => {
      //获取当前文件的绝对路径
      const filedir = path.join(filePath, filename);
      // fs.stat(path)执行后,会将stats类的实例返回给其回调函数。
      fs.stat(filedir, (eror, stats) => {
        if (eror) return console.error('Error:(spec)', err);
        // 是否是文件
        const isFile = stats.isFile();
        // 是否是文件夹
        const isDir = stats.isDirectory();
        if (isFile) {
          // 这块我自己处理了多余的绝对路径,第一个 replace 是替换掉那个路径,第二个是所有满足\\的直接替换掉
          arr.push(filedir.replace(init.get(), '').replace(/\\/img, '/'))
          // 最后打印的就是完整的文件路径了
          if (timer) clearTimeout(timer)
          timer = setTimeout(() => cb && cb(arr), 200)
        }
        // 如果是文件夹
        if (isDir) {
          arr.push(filedir.replace(init.get(), '').replace(/\\/img, '/'))
          fileDisplay(filedir, cb)
        };
      })
    });
  });
}
// 测试代码
// fileDisplay('./src', (arr) => {
//   console.log(arr, '-=')
// })
// commonjs规范
module.exports = fileDisplay;
  1. 然后 xxx/csdn/generators/app/index.js文件内容替换成以下内容。
const Generator = require('yeoman-generator');
const inquirer = require('inquirer');
const fileDisplay = require('../../utils/readFilePath.js')
const path = require('path')
const ejs = require('ejs')
const fs = require('fs')

const exec = require("child_process").exec;

const execNpmi = () => {
  const cmd = 'npm i';
  exec(cmd, {
    maxBuffer: 1024 * 2000,
    stdio: 'inherit',
    shell: true
  }, function (err, stdout, stderr) {
    if (err) {
      console.log(err);
      Promise.reject(err);
    } else if (stderr.lenght > 0) {
      Promise.reject(new Error(stderr.toString()));
    } else {
      console.log(stdout);
      Promise.resolve();
    }
  });
}

module.exports = class extends Generator {
  method1() {
    const _this = this;
    inquirer.prompt([
      /* 在这里配置您的问题(可以设置多个,它们将按顺序向用户提出) */
      {
        type: 'input',
        name: 'name',
        message: '请输入项目名称'
      }
    ]).then(answers => {
      // 回调,对用户输入的答案就行处理
      // 目标目录
      const destDir = process.cwd();
      const tmpDir = path.join(__dirname, 'templates')
      const ejsArr = ['.js', '.ts', '.vue', '.jsx', '.tsx', '.html', '.css', '.json']
      fileDisplay(tmpDir, (arrList) => {
        console.log(arrList, 'arrList')
        // 克隆文件及文件夹
        arrList.forEach(file => {
          fs.stat(path.join(tmpDir, file), (eror, stats) => {
            // 是否是文件
            const isFile = stats.isFile();
            // 是否是文件夹
            const isDir = stats.isDirectory();
            if (isFile) {
              // 如果满足 ejs 的文件规则 则进入 ejs 模板模式
              if (ejsArr.includes(path.extname(file).toLowerCase())) {
                ejs.renderFile(path.join(tmpDir, file), answers, function (err, res) {
                  if (err) return console.log(err, '写入错误');
                  fs.writeFileSync(path.join(destDir, file), res);
                });
              } else {
                // 不满足则直接读取文件并进行拷贝
                fs.readFile(path.join(tmpDir, file), 'utf8', function (err, info) {
                  if (err) return console.log(err)
                  fs.writeFileSync(path.join(destDir, file), info);
                })
              }
            }
            // 如果是文件夹
            if (isDir) {
              fs.mkdirSync(path.join(destDir, file));
            };
          })
        });
        // 执行命令行
        execNpmi();
      })
    });
  }
};
  1. 然后创建模板文件夹xxx/csdn/generators/app/templates。里面内容则为你需要的模板。

  2. 如果你没用模板可以用用我的小模板【注意要切换分支,使用template分支】

  3. 最终去到(d:/xxxxxxxx/use)进入小黑框执行 yo app;下图为最终输出结果(因为会下载依赖会导致界面黑屏卡顿,但是你会看到新增加node_modules还在新增文件,这个就说明是没问题的,需等待一会儿)

在这里插入图片描述

最终说明一下ejs语法

  1. 模板文件更改name为ejs语法就行了(<%= name %>);这个name是我们自己在控制台中输入的值,我们给它定义的名称就为name。所以说这里取值为name。
    在这里插入图片描述
  2. 当你的模板文件中有ejs语法的时候需要这样写(<%%= xxxxxxx %>)表示<%%= xxxxxxx %>编译为<%= xxxxxxx %>
    在这里插入图片描述

项目实例

  1. 项目demo地址(项目相较于页面被优化了一下)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值