前言
在前端工程化浪潮下,脚手架工具已成为提升开发效率、规范项目结构的利器。本文将深入剖析一个现代前端项目生成器的技术实现思路,包括 CLI 交互、模板引擎、配置管理、插件机制等核心技术点,帮助你理解并实现属于自己的脚手架工具。
一、项目架构设计
一个现代 CLI 脚手架的整体架构主要分为以下几个核心模块:
- 命令行交互(CLI):负责与用户交互,收集项目配置信息。
- 模板引擎:根据用户选择渲染项目模板,生成最终代码结构。
- 文件操作与依赖管理:自动化生成文件、安装依赖。
二、核心技术实现
1. 命令行交互
CLI 脚手架通常采用 prompts 实现命令行交互,动态收集用户输入
import prompts from 'prompts'
const main=()=>{
//支持填充默认值
prompts.override({
overwrite: argvOverwrite
})
const result=await prompts([
{
name: 'projectName',
type: argvProjectDir ? null : 'text',
message: yellow('项目名称: '),
initial: targetDir,
},
...等配置
])
}
2. 模板引擎
项目模板通常采用 fs 等模板引擎进行渲染。CLI 脚手架支持变量替换、条件渲染等功能:
const write = (templateDir: string, root: string, { packageName, projectName }: { packageName: string, projectName: string }) => {
const templateFiles = fs.readdirSync(templateDir)
templateFiles.forEach(file => {
const newFile = renameFiles[file] ?? file
const originPath = path.resolve(templateDir, `./${file}`)
const targetPath = path.resolve(root, `./${newFile}`)
//特殊处理package.json
if (newFile === 'package.json') {
const content = getPkgFile(originPath, packageName)
fs.writeFileSync(targetPath, content)
return
}
//如果还有特殊逻辑可以在添加
...
const fileState = fs.statSync(path.resolve(templateDir, `./${file}`))
//递归创建
if (fileState.isDirectory()) {
fs.mkdirSync(targetPath)
write(originPath, targetPath, { packageName, projectName })
} else {
fs.copyFileSync(originPath, targetPath)
}
})
}
//获取模版地址
const templateDir = path.resolve(fileURLToPath(import.meta.url), `../../template-${template}`)
//通过fs模块将文件写入指定位置
write(templateDir, root, {
packageName: packageName ?? projectName ?? argvProjectDir,
projectName: projectName
})
3. 依赖管理
使用 child_process 实现依赖自动安装:
import {execSync} from "child_process"
async function installDeps(projectPath) {
await execSync('npm', ['install'], { cwd: projectPath, stdio: 'inherit' });
那么!为什么我们在终端执行特定的命令就可以执行这个脚手架呢,让我们去看package.json
{
name:"cli",
...
//注意这里是注册命令
bin:{
"key":"path"
}
}
我们可以看到bin为注册命令,key为输入的命令,path为脚本执行路径,这样就可以完成cli脚手架啦。
如果喜欢麻烦大家给个关注哦