前端脚手架的搭建

145 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前端脚手架

解决什么问题?

脚手架就是帮助你把项目的基础架子搭好。例如项目依赖、模板、构建工具等等。让你不用从零开始配置一个项目,尽可能快的进行业务开发。

公司已开发的项目是资产和宝贵经验,包含很多公用的逻辑。把原有项目单纯地复制粘贴存在以下问题:

  • 重复复制粘贴 dirty work
  • 容易忽略项目中的配置
  • 存在业务定制逻辑
  • 项目框架不同。基于 cra/vue-cli/vite。需要整合到一起。

前置准备: 找个项目模板

核心模块

  • 界面交互
  • 下载项目模板

【界面交互】项目初始化

  1. mkdir tracey-cli & cd tracey-cli
  2. npm init -y
  3. mkdir bin 新建 enter.js 文件,在 package.json 中增加 "bin": "bin/enter"
  4. 编辑 enter.js
#!/usr/bin/env node
// 关联依赖 commander 命令行指令配置
// npm i commander 
const { program } = require('commander');
const packageInfo = require('../package');

program.version(packageInfo.version, '-v, --version');

program.name(packageInfo.name)
  .usage(`<command> [option]`)

// 解析参数
program.parse(process.argv);
  1. 终端运行 npm link,添加 --force 可以强制覆盖原有指令

测试:

demo01.png

【界面交互】控制台输出样式

来了解下项目的依赖和这些依赖的简易使用:

  • chalk 命令行样式 *注意版本 4.1.2
  • ora 终端 loading *注意版本 5.1.0
  • figlet 生成终端的艺术字
// bin/enter.js
const chalk = require("chalk");
console.log(chalk.blue.underline.bold("调整样式"))

const ora = require("ora");
// 定义一个loading
const spinner = ora("加载中...");
// 启动loading
spinner.start();
setTimeout(() => {
  spinner.text = "失败";
  spinner.fail();
}, 1000);

const figlet = require("figlet")

console.log(
  "\r\n" +
  figlet.textSync(packageInfo.name, {
    font: "ANSI Shadow",
    horizontalLayout: "default",
    verticalLayout: "default",
    whitespaceBreak: true,
  })
);

route.gif

【界面交互】命令行交互

  • inquirer *注意版本 8.1.4

input|number|confirm 确认|list 单选|rawlist 带序号单选|checkbox 多选

const Inquirer = require('inquirer')

new Inquirer.prompt([
    {
      type: "input",
      name: "email",
      message: "What's your email address?",
      // 校验
      validate: function (value) {
        let pass = value.match(
          /^[a-zA-Z0-9.!#$%&'*+/=?^_`{l}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/); 
        if (pass) {
            return true;
          }
        return "Please enter a valid email address.";

      },
    },
    // 多选交互功能
  {
    name: "react",
    // 单选将这里修改为 list 即可
    type: "checkbox",
    message: "选择项目所需功能",
    choices: [
      {
        name: "Babel",
        checked: true,
      },
      {
        name: "TypeScript",
      },
      {
        name: "Router",
      },
    ],
    // 选择分支,可通过when实现
    whenfunction (answers) {  
      return answers.computerLanguage == "JavaScript'  
    }
  },
]).then((data) => {
  console.log(data);
});

route.gif

ejs

const ejs = require('ejs')
const destUrl = path.join(__dirname, 'templates');

// 交互
// 模版文件目录
const destUrl = path.join(__dirname, 'templates'); 
// 生成文件目录
// process.cwd() 对应控制台所在目录
const cwdUrl = process.cwd();
// 从模版目录中读取文件
fs.readdir(destUrl, (err, files) => {
if (err) throw err;
files.forEach((file) => {
    // 使用 ejs 渲染对应的模版文件
    // renderFile(模版文件地址,传入渲染数据)
    ejs.renderFile(path.join(destUrl, file), answers).then(data => {
    // 生成 ejs 处理后的模版文件
    fs.writeFileSync(path.join(cwdUrl, file) , data)
    })
  })
})

【项目模板】项目模板

获取项目模板 git clone or fs-extra

项目模板没有选择内部维护,如果想要内部维护的话可以选择 fs-extra 读取

const path = require('path')
const crossSpawn = require('cross-spawn')

const spawn = (command, args = [], options = {}) => {
  return new Promise((resolve) => {
    const cmd = spawn(command, args, Object.assign({ stdio: 'inherit', shell: true, cwd: '' }, options))
    cmd.on('close', code => {
      if (code !== 0) {
        return resolve({ command: `${command} ${args.join(' ')}` });
      }
      resolve();
    });
  })
}

// 下载模板
function download(project, git) {
  const cwd = path.join(process.cwd(), `${project}`);
  startLoad('', '下载中...');
  return new Promise(async (resolve, reject) => {
    let r = await spawn(`git`, ['clone', `${git.url}`, `${project}`, '-v', '--progress']);
    endLoad()
    if (r) {
      red('下载失败')
      return false
    }
    green('下载成功!');
    if (git.branch) {
      await spawn(`git`, ['checkout', `${git.branch}`], { cwd });
    }
    // 删除项目里的 .git 文件夹
    await remove(`./${project}/.git`);
    await spawn(`git`, [`init`], { cwd })
    if (r) return reject(err);
    return resolve(true)
  })
}

项目源码

项目源码

参考资料:

战场小包 【前端架构必备】手摸手带你搭建一个属于自己的脚手架

手把手教你写一个脚手架