本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前端脚手架
解决什么问题?
脚手架就是帮助你把项目的基础架子搭好。例如项目依赖、模板、构建工具等等。让你不用从零开始配置一个项目,尽可能快的进行业务开发。
公司已开发的项目是资产和宝贵经验,包含很多公用的逻辑。把原有项目单纯地复制粘贴存在以下问题:
- 重复复制粘贴 dirty work
- 容易忽略项目中的配置
- 存在业务定制逻辑
- 项目框架不同。基于 cra/vue-cli/vite。需要整合到一起。
前置准备: 找个项目模板
核心模块
- 界面交互
- 下载项目模板
【界面交互】项目初始化
mkdir tracey-cli & cd tracey-cli
npm init -y
mkdir bin
新建enter.js
文件,在package.json
中增加"bin": "bin/enter"
- 编辑
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);
- 终端运行
npm link
,添加--force
可以强制覆盖原有指令
测试:
【界面交互】控制台输出样式
来了解下项目的依赖和这些依赖的简易使用:
- 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, }) );
【界面交互】命令行交互
- inquirer *注意版本
8.1.4
const Inquirer = require('inquirer') // 多选交互功能 new Inquirer.prompt([ { name: "react", // 单选将这里修改为 list 即可 type: "checkbox", message: "选择项目所需功能", choices: [ { name: "Babel", checked: true, }, { name: "TypeScript", }, { name: "Router", }, ], }, ]).then((data) => { console.log(data); });
【项目模板】项目模板
- cross-spawn
获取项目模板 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) }) }
项目源码
参考资料: