为什么我们需要脚手架?
当公司项目逐渐增多,如何快速搭建符合团队技术栈的新项目。不是简单的复制粘贴。
而是需要一个贴合团队的脚手架来帮助我们减少这些重复性工作,提高开发效率。
前端三大框架也各自有自己的脚手架。
| React | Vue | Angular |
|---|---|---|
| create-react-app | vue-cli | angular-cli |
但是真正落地到团队项目,我们在其基础上还需要引入:项目个性化配置、流水线配置、统一版本的第三方库等等。很显然,官方脚手架并不是一个很好的选择。
接下来介绍如何快速生成一个通用项目脚手架。
首先要确定我们的需求。我们需要脚手架帮我们做到什么?
1、自动生成新项目
2、可选择的多个项目模板
3、可选择的多种配置
我们开始吧!
创建项目
mkdir my-cli
cd my-cli
npm init
生成 package.json 文件
添加 cli.js
touch cli.js
在 cli.js 中添加脚本命令
#! /usr/bin/env node
console.log('hello')
这里第一行的意思是 表明脚本是 node 环境,/usr/bin/env 是用来查找node的bin目录,找node执行文件来执行当前脚本文件。
在命令行输入 node cli.js 即可看到输出。
但是我们需要指定命令名称来执行 cli。如何做呢?
node内置了对命令行操作的支持,在package.json中的bin字段下可以定义命令名和其关联的执行文件。
我们修改 package.json
{
"name": "my-cli",
...
"bin": {
"my-cli": "./cli.js"
}
}
代表用 my-cli 执行 cli.js 脚本文件。
我们执行 npm link,在对应的 node /node_modules/.bin 下创建软连接。
执行 my-cli,就可以看到输出了。
刚才示范了一个简单的 cli 执行的流程,接下来我们开始进入正题。
1、添加 create 命令
使用 commander 来实现
1、添加create命令
2、读取用户填写的项目名称
const commander = require('commander');
commander
.command('create <name>')
.action((name, options) => {
console.log(name)
})
.parse(process.argv)
2、选择模板
使用 inquirer 来实现
1、可选择创建的模板
const inquirer = require('inquirer');
const selectTemplate = async () => {
return await inquirer.prompt([
{
name: 'template',
type: 'list',
message: 'Select a template:',
choices: [
{
name: 'react',
value: 'react',
},
{
name: 'vue',
value: 'vue',
},
],
},
]);
};
3、创建模板
1、克隆模板
直接执行 git clone xxx
const { execSync } = require('child_process')
execSync(`git clone ${gitUri}`)
2、处理用户输入
使用 ejs 模板引擎
IF 语句<% if (name) { %> <% } %>
替换语句<%= name %>
<% if (name) { %>
<h2><%= name %></h2>
<% } %>
使用ejs,可以按需加载代码以及第三方库,只需要判断用户输入即可,这里只给最简单的示例。
通过判断用户输入,替换模板的内容
const writeTemplate = (templateDir, targetDir, name) => {
const files = fs.readdirSync(templateDir);
files.forEach(file => {
const templateFile = path.join(templateDir, file); // 模板文件
const targetFile = path.join(targetDir, file); // 目标文件
const stats = fs.statSync(templateFile);
if (stats.isDirectory()) {
writeTemplate(templateFile, targetFile, name);
} else {
fs.ensureFileSync(targetFile);
ejs.renderFile(templateFile, { name }).then(data => {
fs.writeFileSync(targetFile, data);
});
}
});
}
发布到 npm
使用 npm publish, 登录后发布到 npm
可能会用到的其他工具库
1、ora Loading 动画
2、chalk 彩色输出
3、madge 分析文件依赖
大功告成!又可以愉快的摸鱼了!!!