'# 我开源了一个同时支持 react、vue、react组件库和普通 Typescript库的前端脚手架
一、背景与问题
在现代前端开发中,框架选择的多样性带来了显著的工程挑战。一个典型的前端项目可能同时包含:
- React 组件库(用于业务模块)
- Vue 项目(用于主应用)
- React 组件库(用于第三方UI组件)
- 普通 TypeScript 库(用于通用工具函数)
传统脚手架工具往往需要为每个框架单独开发,导致重复代码和配置冗余。我设计的这个脚手架通过统一的模板引擎和智能检测机制,实现了:
- 自动识别项目类型(React/Vue/普通TS库)
- 生成框架专属的配置文件(tsconfig、webpack、vite等)
- 支持组件库的标准化输出
- 统一的代码规范和类型定义
这解决了多个实际问题:避免框架间配置冲突、简化多项目管理、提高代码复用率。
二、基本原理
该脚手架的核心是多模板引擎架构和智能检测机制,其工作原理如下:
- 项目类型检测:通过分析项目结构中的关键文件(如
package.json、vite.config.ts等)识别框架类型 - 模板引擎:使用Handlebars作为模板引擎,支持动态生成配置文件
- 配置文件生成:根据检测结果生成对应框架的配置文件(tsconfig、webpack、vite等)
- 组件库规范:为不同框架定义统一的组件库结构规范(如React的
index.ts导出,Vue的index.js导出)
三、环境准备
# 安装依赖
npm install -g @typescript-scaffold/cli
# 创建项目
typescript-scaffold create my-project
项目结构示例:
my-project/
├── package.json
├── tsconfig.json
├── vite.config.ts
├── src/
│ ├── react/
│ ├── vue/
│ └── utils/
├── tests/
└── .eslintrc.cjs
四、核心实现
1. 项目类型检测模块
// src/detector.ts
export function detectProjectType(root: string): string {
const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8'));
// 判断是否为React项目
if (packageJson.dependencies?.react || packageJson.dependencies?.react_dom) {
return 'react';
}
// 判断是否为Vue项目
if (packageJson.dependencies?.vue) {
return 'vue';
}
// 默认为普通TS库
return 'ts';
}
关键点说明:
- 通过
package.json中的依赖项判断框架类型 - 支持同时存在多个框架依赖的情况(需用户手动指定)
- 检测逻辑可扩展,可添加对Svelte、SolidJS等框架的支持
2. 配置文件生成器
// src/generator.ts
export function generateConfig(type: string, root: string): void {
const template = fs.readFileSync(path.join(__dirname, `templates/${type}.hbs`), 'utf-8');
const config = Handlebars.compile(template)({ root });
fs.writeFileSync(path.join(root, 'tsconfig.json'), config);
}
模板文件示例(tsconfig.hbs):
{
"compilerOptions": {
"target": "ES2021",
"module": "ESNext",
"jsx": "{{ type === 'react' ? 'react' : 'preserve' }}",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist"
},
"include": ["src"]
}
关键点说明:
- 使用Handlebars模板引擎实现动态配置
- 支持不同框架的特殊配置(如React的jsx配置)
- 可扩展为生成webpack/vite配置文件
3. 组件库生成器
// src/component-generator.ts
export function generateComponentLibrary(type: string, root: string): void {
const template = fs.readFileSync(path.join(__dirname, `templates/component-${type}.ts`), 'utf-8');
if (type === 'react') {
fs.writeFileSync(path.join(root, 'src/react/index.ts'), template);
} else if (type === 'vue') {
fs.writeFileSync(path.join(root, 'src/vue/index.js'), template);
}
}
模板文件示例(component-react.ts):
// src/react/index.ts
export * from './components/Button';
export * from './components/Modal';
关键点说明:
- 为不同框架定义统一的导出规范
- 支持按需导出组件
- 可扩展为支持组件库版本控制
五、完整案例
创建一个同时包含React组件库和Vue项目的项目:
typescript-scaffold create my-multi-project
项目结构:
my-multi-project/
├── package.json
├── tsconfig.json
├── vite.config.ts
├── src/
│ ├── react/
│ │ ├── components/
│ │ │ ├── Button.tsx
│ │ │ └── Modal.tsx
│ │ └── index.ts
│ ├── vue/
│ │ ├── components/
│ │ │ ├── Button.vue
│ │ │ └── Modal.vue
│ │ └── index.js
│ └── utils/
├── tests/
└── .eslintrc.cjs
运行项目:
# 进入React项目
cd my-multi-project/src/react
npm install
npm start
# 进入Vue项目
cd my-multi-project/src/vue
npm install
npm start
关键点说明:
- 通过
package.json的workspaces字段实现多项目管理 - 使用Vite的多项目支持特性
- 每个子项目都有独立的配置文件
六、源码解析
1. 模板引擎核心逻辑
// src/generator.ts
const handlebars = require('handlebars');
// 注册自定义helper
handlebars.registerHelper('ifEq', function (a, b, opts) {
return a === b ? opts.fn(this) : opts.inverse(this);
});
// 注册自定义helper
handlebars.registerHelper('ifNotEq', function (a, b, opts) {
return a !== b ? opts.fn(this) : opts.inverse(this);
});
关键点说明:
- 自定义helper实现条件判断
- 支持复杂模板逻辑
- 可扩展为支持更多模板功能
2. 配置文件生成逻辑
// src/generator.ts
export function generateConfig(type: string, root: string): void {
const template = fs.readFileSync(path.join(__dirname, `templates/${type}.hbs`), 'utf-8');
const config = Handlebars.compile(template)({ root });
fs.writeFileSync(path.join(root, 'tsconfig.json'), config);
}
关键点说明:
- 使用Handlebars模板引擎生成配置文件
- 支持动态变量插入
- 可扩展为生成其他配置文件
3. 组件库生成逻辑
// src/component-generator.ts
export function generateComponentLibrary(type: string, root: string): void {
const template = fs.readFileSync(path.join(__dirname, `templates/component-${type}.ts`), 'utf-8');
if (type === 'react') {
fs.writeFileSync(path.join(root, 'src/react/index.ts'), template);
} else if (type === 'vue') {
fs.writeFileSync(path.join(root, 'src/vue/index.js'), template);
}
}
关键点说明:
- 为不同框架生成不同格式的导出文件
- 支持组件库的统一管理
- 可扩展为支持更多框架
七、进阶使用
1. 自定义模板系统
创建自定义模板文件:
my-project/
├── templates/
│ ├── custom.hbs
│ └── custom.ts
使用自定义模板创建项目:
typescript-scaffold create my-project --template custom
2. 多框架支持策略
// src/detector.ts
export function detectProjectType(root: string): string {
const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8'));
// 判断是否为React项目
if (packageJson.dependencies?.react || packageJson.dependencies?.react_dom) {
return 'react';
}
// 判断是否为Vue项目
if (packageJson.dependencies?.vue) {
return 'vue';
}
// 判断是否为Svelte项目
if (packageJson.dependencies?.svelte) {
return 'svelte';
}
// 默认为普通TS库
return 'ts';
}
关键点说明:
- 支持更多框架的检测
- 可扩展为支持其他框架
- 需要维护不同框架的模板
3. 配置文件缓存机制
// src/generator.ts
const cache = new Map<string, string>();
export function generateConfig(type: string, root: string): void {
const key = `${type}-${root}`;
if (cache.has(key)) {
return;
}
const template = fs.readFileSync(path.join(__dirname, `templates/${type}.hbs`), 'utf-8');
const config = Handlebars.compile(template)({ root });
fs.writeFileSync(path.join(root, 'tsconfig.json'), config);
cache.set(key, config);
}
关键点说明:
- 避免重复生成相同配置
- 提高性能
- 可扩展为支持其他缓存策略
八、性能与工程实践
1. 性能优化
- 使用模板缓存机制减少重复生成
- 使用异步加载模板文件
- 对大项目使用分块生成策略
- 增加配置文件压缩功能
2. 异常处理
// src/generator.ts
try {
const template = fs.readFileSync(...);
const config = Handlebars.compile(template)({ root });
fs.writeFileSync(...);
} catch (error) {
console.error('配置文件生成失败:', error);
process.exit(1);
}
关键点说明:
3. 安全考虑
- 对用户输入进行严格校验
- 限制模板文件的访问权限
- 使用安全的模板引擎
- 增加代码签名验证
九、常见问题与踩坑
1. 配置文件冲突问题
错误示例:
{
"compilerOptions": {
"jsx": "react",
"module": "ESNext"
}
}
问题分析: 如果项目同时使用React和Vue,会导致配置冲突。
解决办法:
- 使用框架专用的配置文件
- 通过
package.json的workspaces字段管理多项目 - 使用
tsconfig.json的extends特性
2. 组件库导出问题
错误示例:
// react/index.ts
export * from './components/Button';
问题分析: 如果组件库未正确导出,会导致模块引用失败。
解决办法:
3. 模板注入漏洞
错误示例:
{{ user.name }}
问题分析: 如果未正确转义用户输入,可能导致模板注入攻击。
解决办法:
- 使用
{{{ }}}进行原始输出 - 增加输入校验
- 使用安全的模板引擎
十、最佳实践
- 统一规范:为不同框架定义统一的组件导出规范
- 版本控制:对模板文件进行版本控制
- 安全校验:对用户输入进行严格校验
- 性能优化:使用缓存机制提高性能
- 文档完善:提供详细的使用文档和示例
- 持续集成:集成到CI/CD流程中
- 扩展性:设计可扩展的架构支持新框架
十一、总结
这个脚手架通过多模板引擎架构和智能检测机制,实现了对多种前端框架的统一支持。它解决了传统脚手架在处理多框架项目时的配置冲突和代码冗余问题,同时提供了良好的扩展性。适用于需要同时维护多个前端项目的企业级开发场景,但不适合小型项目或对性能有极高要求的场景。在使用过程中需要注意配置文件的版本控制、安全校验和异常处理,以确保项目的稳定性和可维护性。