cli-admin-template
v1.0.0
Published
脚手架本质就是一个工具,作用是能够让使用者专注于写代码,它可以让我们只用一个命令就生成一个已经配置好的项目,而不用我们再花时间去配置和安装相关依赖,可以在很大程度上提升我们的开发效率。比如我们常用的`create-vue`和`create-react-app`就是脚手架,很多大厂也都有自己的脚手架。
Downloads
4
Readme
从0-1实现一个前端脚手架
介绍
为什么需要脚手架?
脚手架本质就是一个工具,作用是能够让使用者专注于写代码,它可以让我们只用一个命令就生成一个已经配置好的项目,而不用我们再花时间去配置和安装相关依赖,可以在很大程度上提升我们的开发效率。比如我们常用的create-vue
和create-react-app
就是脚手架,很多大厂也都有自己的脚手架。
一个脚手架应该具备哪些功能?
我们以vue官方的脚手架create-vue
为例来分析下一个脚手架应该具备哪些功能?
运行命令创建项目
➜ npm create vue@latest
用户根据自己需要选择一些配置项
根据选择的配置项会生成一个模版项目
通过分析create-vue
,我们可以知道,一个脚手架如果想要创建一个项目,最少要有以下两点功能:
- 可以通过命令行和用户交互
- 根据交互的结果去生成对应的模版项目
脚手架实现
初始化项目
- 执行如下初始化命令
➜ mkdir kfc-vme50
➜ cd kfc-vme50
➜ npm init -y
- 在根目录下创建
bin/index.js
文件作为入口文件,并添加如下代码
#!/usr/bin/env node
console.log('肯德基疯狂星期四v我50')
- 在package.json中添加bin字段
"bin": {
"kfc-vme50": "/bin/index.js"
}
- 在根目录下执行
npm link
将项目链接到本地环境,就可以实现kfc-vme50
命令全局调用 - 运行
kfc-vme50
并查看控制台输出
相关依赖
实现一个脚手架,通常会用到以下依赖包
- commander:命令行处理工具
- chalk:命令行输出美化工具
- inquirer:命令行交互工具
- ora:终端loading美化工具
- git-clone:下·载项目模版工具
- figlet:终端生成艺术字
- fs-extra:用来操作本地目录
talk is cheap, show me the code
#!/usr/bin/env node
const inquirer = require('inquirer');
const { program } = require('commander');
const figlet = require('figlet');
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const gitClone = require('git-clone');
const ora = require('ora');
const projectList = {
'vue': '[email protected]:kfc-vme50/vue-template.git',
'react': '[email protected]:kfc-vme50/react-template.git',
'react&ts': '[email protected]:kfc-vme50/react-template-ts.git',
'vue&ts': '[email protected]:kfc-vme50/vue-template-ts.git',
}
// 修改帮助信息的首行展示
program.usage('<command> [options]')
// 版本号
program.version(`v${require('../package.json').version}`)
// 艺术字展示
program.on('--help', function () {
console.log(
figlet.textSync('kfc vme50', {
font: 'Ghost',
horizontalLayout: 'default',
verticalLayout: 'default',
width: 100,
whitespaceBreak: true
})
)
});
// 创建项目的命令
program
.command('create <app-name>')
.description('创建新项目')
.option('-f, --force', '如果创建的目录存在则强制删除')
.action(async function (name, option) {
const cwd = process.cwd();
const targetPath = path.join(cwd, name);
// 如果文件夹存在
if (fs.existsSync(targetPath)) {
if (option.force) {
fs.remove(targetPath)
} else {
const res = await inquirer.prompt([
{
name: 'action',
type: 'list',
message: '是否覆盖已有文件夹?',
choices: [
{
name: 'YES',
value: true
},
{
name: 'NO',
value: false
}
]
}
])
if (!res.action) {
return;
} else {
fs.remove(targetPath)
console.log(chalk.red('已删除之前的文件夹'))
}
}
}
const res = await inquirer.prompt([
{
name: 'type',
type: 'list',
message: '请选择使用的框架',
choices: [
{
name: 'Vue',
value: 'vue'
},
{
name: 'React',
value: 'react'
}
]
},
{
name: 'ts',
type: 'list',
message: '是否使用ts项目',
choices: [
{
name: 'YES',
value: true
},
{
name: 'NO',
value: false
}
]
}
])
const rep = res.type + (res.ts ? '&ts' : '');
// 拉取项目模板
const spinner = ora('正在加载项目模板...').start();
gitClone(
projectList[rep],
targetPath,
{
checkout: 'main'
},
(err) => {
if (!err) {
fs.remove(path.resolve(targetPath, '.git'));
spinner.succeed('项目模板加载完成!');
console.log('now run:')
console.log(chalk.green(`\n cd ${name}`))
console.log(chalk.green(' npm install'))
console.log(chalk.green(` npm run ${res.type === 'react' ? 'start' : 'dev'}\n`))
} else {
spinner.fail(chalk.red('项目模板加载失败,请重新获取!'));
}
}
)
})
program.parse(process.argv)
发布
- 注册npm账号
- 在本地登录并发布
# 登录刚注册的账号
➜ npm login
Username: 用户名
Password: 密码
Email: 注册邮箱
Enter one-time password: 一次性密码 邮箱会收到邮件
# 在我们脚手架的根目录下执行发布命令
➜ npm publish
注意:
登录和发包前一定要先查看npm的源,需要修改为
https://registry.npmmirror.com
在发布时包名不能重复,所以可以先在线上搜索下看看有没有存在的包,如果出现403错误可能是包名和线上的包重复了,修改package.json中的name即可